home *** CD-ROM | disk | FTP | other *** search
/ PC Format (South-Africa) 2001 June / PCFJune.iso / mweb / MWEB Utils / ws295sdk.exe / Ws2sdkzp.exe / SAMPLES / LAYERED / SPI.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-06  |  113.0 KB  |  3,978 lines

  1. /*++
  2.  
  3.      Copyright (c) 1996 Intel Corporation
  4.      Copyright (c) 1996 Microsoft Corporation
  5.      All Rights Reserved
  6.  
  7.      Permission is granted to use, copy and distribute this software and
  8.      its documentation for any purpose and without fee, provided, that
  9.      the above copyright notice and this statement appear in all copies.
  10.      Intel makes no representations about the suitability of this
  11.      software for any purpose.  This software is provided "AS IS."
  12.  
  13.      Intel specifically disclaims all warranties, express or implied,
  14.      and all liability, including consequential and other indirect
  15.      damages, for the use of this software, including liability for
  16.      infringement of any proprietary rights, and including the
  17.      warranties of merchantability and fitness for a particular purpose.
  18.      Intel does not assume any responsibility for any errors which may
  19.      appear in this software nor any responsibility to update it.
  20.  
  21. Module Name:
  22.  
  23.     SPI.CPP :
  24.  
  25. Abstract:
  26.  
  27.     Contains all the entry points for the WS2SPI.  This module implements a
  28.     sample WinSock2 layered service provider.
  29.  
  30. --*/
  31.  
  32. #include "precomp.h"
  33.  
  34.  
  35. // The WinSock2 UpcallTable.
  36. WSPUPCALLTABLE                        gUpCallTable;
  37. LPWPUCOMPLETEOVERLAPPEDREQUEST        lpWPUCompleteOverlappedRequest;
  38.  
  39. // Variables to track Startup/Cleanup Pairing.
  40. CRITICAL_SECTION  gInitCriticalSection;
  41. DWORD             gStartupCount=0;
  42.  
  43.  
  44. // The catalog of providers
  45. PDCATALOG gProviderCatalog;
  46.  
  47. // The worker thread for overlapped functions
  48. #define UNINITIALIZED_THREAD    ((PDWORKERTHREAD)-1)
  49. PDWORKERTHREAD gWorkerThread=UNINITIALIZED_THREAD;
  50.  
  51. // The window for translation of async select messages
  52. #define UNINITIALIZED_WINDOW    ((PDASYNCWINDOW)-1)
  53. PDASYNCWINDOW gAsyncWindow=UNINITIALIZED_WINDOW;
  54.  
  55. // The buffer manager for providers that modify the data stream
  56. PDBUFFERMANAGER gBufferManager;
  57.  
  58. char    gLibraryName[MAX_PATH] ="LSP.DLL";
  59.  
  60. #define SetBlockingProvider(Provider)        \
  61.     (TlsIndex!=0xFFFFFFFF)                    \
  62.         ? TlsSetValue (TlsIndex, Provider)    \
  63.         : NULL
  64.  
  65. #define GetBlockingProvider()                \
  66.     (TlsIndex!=0xFFFFFFFF)                    \
  67.         ? TlsGetValue (TlsIndex)            \
  68.         : NULL
  69.  
  70. PDASYNCWINDOW
  71. GetAsyncWindow (
  72.     )
  73. /*++
  74. Routine Description:
  75.  
  76.     Gets the pointer to async window object (creates and initializes
  77.     the object if not already created)
  78. Arguments:
  79.     None
  80. Return Value:
  81.     Pointer to async window object if successfull, NULL otherwise
  82.     
  83. --*/
  84. {
  85.     // Quick check if object was already initialized (it can be NULL
  86.     // if we failed initialization in which case we do not
  87.     // want to retry)
  88.     if (gAsyncWindow!=UNINITIALIZED_WINDOW)
  89.         ;
  90.     else {
  91.         EnterCriticalSection (&gInitCriticalSection);
  92.         // Recheck under protection of the critical section
  93.         if (gAsyncWindow == UNINITIALIZED_WINDOW) {
  94.             PDASYNCWINDOW   asyncWindow;
  95.             // Attempt to create and initialize the object
  96.             // If creation or initialization fails, set global object
  97.             // pointer to NULL to prevent further initialization attepmts
  98.             asyncWindow = new DASYNCWINDOW;
  99.             if (asyncWindow!=NULL) {
  100.                 if (asyncWindow->Initialize()==NO_ERROR) {
  101.                     gAsyncWindow = asyncWindow;
  102.                 }
  103.                 else {
  104.                     delete asyncWindow;
  105.                     gAsyncWindow = NULL;
  106.                 }
  107.             }
  108.         }
  109.         LeaveCriticalSection (&gInitCriticalSection);
  110.     }
  111.     return gAsyncWindow;
  112. }
  113.  
  114.  
  115. PDWORKERTHREAD
  116. GetWorkerThread (
  117.     )
  118. /*++
  119. Routine Description:
  120.  
  121.     Gets the pointer to worker thread object (creates and initializes
  122.     the object if not already created)
  123. Arguments:
  124.     None
  125. Return Value:
  126.     Pointer to worker thread object if successfull, NULL otherwise
  127.     
  128. --*/
  129. {
  130.     // Quick check if object was already initialized (it can be NULL
  131.     // if we failed initialization in which case we do not
  132.     // want to retry)
  133.     if (gWorkerThread!=UNINITIALIZED_THREAD)
  134.         ;
  135.     else {
  136.         EnterCriticalSection (&gInitCriticalSection);
  137.         // Recheck under protection of the critical section
  138.         if (gWorkerThread == UNINITIALIZED_THREAD) {
  139.             PDWORKERTHREAD  workerThread;
  140.             // Attempt to create and initialize the object
  141.             // If creation or initialization fails, set global object
  142.             // pointer to NULL to prevent further initialization attepmts
  143.             workerThread = new DWORKERTHREAD;
  144.             if (workerThread!=NULL) {
  145.                 if (workerThread->Initialize()==NO_ERROR) {
  146.                     gWorkerThread = workerThread;
  147.                 }
  148.                 else {
  149.                     delete workerThread;
  150.                     gWorkerThread = NULL;
  151.                 }
  152.             }
  153.         }
  154.         LeaveCriticalSection (&gInitCriticalSection);
  155.     }
  156.     return gWorkerThread;
  157. }
  158.  
  159.  
  160. SOCKET
  161. WSPAPI
  162. WSPAccept(
  163.     IN SOCKET s,
  164.     OUT struct sockaddr FAR *addr,
  165.     OUT INT FAR *addrlen,
  166.     IN LPCONDITIONPROC lpfnCondition,
  167.     IN DWORD dwCallbackData,
  168.     OUT INT FAR *lpErrno
  169.     )
  170. /*++
  171. Routine Description:
  172.  
  173.     Conditionally  accept a connection based on the return value of a condition
  174.     function, and optionally create and/or join a socket group.
  175.  
  176. Arguments:
  177.  
  178.     s              - A  descriptor  identiying  a socket which is listening for
  179.                      connections after a WSPListen().
  180.  
  181.     addr           - An optional pointer to a buffer which receives the address
  182.                      of   the  connecting  entity,  as  known  to  the  service
  183.                      provider.   The  exact  format  of  the  addr arguement is
  184.                      determined  by  the  address  family  established when the
  185.                      socket was created.
  186.  
  187.     addrlen        - An  optional  pointer  to  an  integer  which contains the
  188.                      length of the address addr.
  189.  
  190.     lpfnCondition  - The  procedure  instance address of an optional, WinSock 2
  191.                      client  supplied  condition  function  which  will make an
  192.                      accept/reject  decision  based  on  the caller information
  193.                      passed  in  as  parameters,  and optionally creaetd and/or
  194.                      join  a  socket group by assigning an appropriate value to
  195.                      the result parameter of this function.
  196.  
  197.     dwCallbackData - Callback data to be passed back to the WinSock 2 client as
  198.                      a  condition  function  parameter.   This parameter is not
  199.                      interpreted by the service provider.
  200.  
  201.     lpErrno        - A pointer to the error code.
  202.  
  203. Return Value:
  204.  
  205.     If  no  error occurs, WSPAccept() returns a value of type SOCKET which is a
  206.     descriptor  for  the accepted socket.  Otherwise, a value of INVALID_SOCKET
  207.     is returned, and a specific error code is available in lpErrno.
  208.  
  209. --*/
  210. {
  211.     INT          ReturnValue;
  212.     PDPROVIDER   Provider;
  213.     PDSOCKET     Socket;
  214.     PDSOCKET     NewSocket;
  215.     SOCKET       ProviderSocket;
  216.     SOCKET       NewProviderSocket;
  217.     DWORD         ThisProviderCatalogEntryId;
  218.  
  219.  
  220.     // Debug/Trace stuff
  221.  
  222.     if (PREAPINOTIFY(( DTCODE_WSPAccept,
  223.                        &ReturnValue,
  224.                        gLibraryName,
  225.                        &s,
  226.                        &addr,
  227.                        &addrlen,
  228.                        &lpfnCondition,
  229.                        &dwCallbackData,
  230.                        &lpErrno)) ) {
  231.         return(ReturnValue);
  232.     }
  233.  
  234.     //
  235.     // Get our DSOCKET object
  236.     //
  237.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  238.         s,
  239.         (DWORD*)&Socket,
  240.         lpErrno);
  241.  
  242.     if (SOCKET_ERROR != ReturnValue){
  243.  
  244.         Provider = Socket->GetDProvider();
  245.         ProviderSocket = Socket->GetProviderSocket();
  246.  
  247.         SetBlockingProvider (Provider);
  248.         NewProviderSocket = Provider->WSPAccept(
  249.             ProviderSocket,
  250.             addr,
  251.             addrlen,
  252.             lpfnCondition,
  253.             dwCallbackData,
  254.             lpErrno);
  255.         SetBlockingProvider (NULL);
  256.  
  257.         if (INVALID_SOCKET != NewProviderSocket){
  258.  
  259.             //
  260.             // Create a new socket object and initialize it.
  261.             NewSocket = new DSOCKET;
  262.             if (NewSocket){
  263.                 ThisProviderCatalogEntryId = 
  264.                     gProviderCatalog->GetLocalProvider()->GetProtocolInfo()->dwCatalogEntryId;
  265.  
  266.                 ReturnValue = gUpCallTable.lpWPUCreateSocketHandle(
  267.                     ThisProviderCatalogEntryId,
  268.                     (DWORD) NewSocket,
  269.                     lpErrno);
  270.                 DEBUGF( DBG_TRACE,
  271.                         ("Accept Returning Socket %X\n", ReturnValue));
  272.  
  273.                 if (INVALID_SOCKET != ReturnValue){
  274.                     NewSocket->Initialize(
  275.                         Provider,
  276.                         NewProviderSocket,
  277.                         Socket->GetCatalogEntryId(),
  278.                         ReturnValue);
  279.  
  280.                 } //if
  281.                 else{
  282.                     delete NewSocket;
  283.                     Provider->WSPCloseSocket (NewProviderSocket, lpErrno);
  284.                 } //else
  285.             } //if
  286.         } //if
  287.     } //if
  288.  
  289.     POSTAPINOTIFY(( DTCODE_WSPAccept,
  290.                     &ReturnValue,
  291.                     gLibraryName,
  292.                     &s,
  293.                     &addr,
  294.                     &addrlen,
  295.                     &lpfnCondition,
  296.                     &dwCallbackData,
  297.                     &lpErrno));
  298.  
  299.     return(ReturnValue);
  300. }
  301.  
  302.  
  303.  
  304. BOOL
  305. PASCAL FAR
  306. WSPAcceptEx (
  307.     IN SOCKET sListenSocket,
  308.     IN SOCKET sAcceptSocket,
  309.     IN PVOID lpOutputBuffer,
  310.     IN DWORD dwReceiveDataLength,
  311.     IN DWORD dwLocalAddressLength,
  312.     IN DWORD dwRemoteAddressLength,
  313.     OUT LPDWORD lpdwBytesReceived,
  314.     IN LPOVERLAPPED lpOverlapped
  315.     )
  316. /*++
  317. Routine Description:
  318.     Accepts a new connection, returns the local and remote address,
  319.     and receives the first block of data sent by the client application.
  320.  
  321. Arguments:
  322.     sListenSocket        - A descriptor identifying a socket that has 
  323.                         already been called with the listen function. 
  324.                         A server application waits for attempts to
  325.                         connect on this socket.
  326.     sAcceptSocket        - A descriptor identifying a socket on which to
  327.                         accept an incoming connection. This socket must 
  328.                         not be bound or connected.
  329.     lpOutputBuffer        - A pointer to a buffer that receives the first 
  330.                         block of data sent on a new connection,
  331.                         the local address of the server, and the remote 
  332.                         address of the client. The receive data is 
  333.                         written to the first part of the buffer starting 
  334.                         at offset zero, while the addresses are written 
  335.                         to the latter part of the buffer. This parameter 
  336.                         must be specified.
  337.     dwReceiveDataLength - The number of bytes in the buffer that will be
  338.                         used for receiving data. If this parameter is 
  339.                         specified as zero, then no receive operation is 
  340.                         performed in conjunction with accepting the connection.
  341.                         Instead, the AcceptEx function completes as soon 
  342.                         as a connection arrives without waiting for any 
  343.                         data.
  344.     dwLocalAddressLength -  The number of bytes reserved for the local
  345.                         address information. This must be at least 
  346.                         16 bytes more than the maximum address length 
  347.                         for the transport protocol in use.
  348.     dwRemoteAddressLength - The number of bytes reserved for the remote 
  349.                         address information. This must be at least 
  350.                         16 bytes more than the maximum address length 
  351.                         for the transport protocol in use. 
  352.     lpdwBytesReceived    - A pointer to a DWORD that receives the count 
  353.                         of bytes received. This is set only if the 
  354.                         operation completes synchronously. 
  355.                         If it returns ERROR_IO_PENDING and is completed 
  356.                         later, then this DWORD is never set and you must 
  357.                         obtain the number of bytes read from the 
  358.                         completion notification mechanism.
  359.     lpOverlapped        - An OVERLAPPED structure that is used to process
  360.                         the request. This parameter must be specified;
  361.                         it cannot be NULL.
  362.  
  363. Return Value:
  364.  
  365.     If no error occurs, the AcceptEx function completed successfully
  366.     and a value of TRUE is returned. 
  367.     If the function fails, AcceptEx returns FALSE. The WSAGetLastError 
  368.     function can then be called to return extended error information.
  369.     If WSAGetLastError returns ERROR_IO_PENDING, then the operation 
  370.     was successfully initiated and is still in progress
  371.  
  372. --*/
  373.  
  374.   {
  375.     PDSOCKET    ListenSocket, AcceptSocket;
  376.     INT            Errno, ReturnValue;
  377.     PDPROVIDER    Provider;
  378.     SOCKET        ProviderListenSocket, ProviderAcceptSocket;
  379.     //
  380.     // Get our DSOCKET objects
  381.     //
  382.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  383.         sListenSocket,
  384.         (DWORD*)&ListenSocket,
  385.         &Errno);
  386.  
  387.     if (SOCKET_ERROR != ReturnValue){
  388.         ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  389.             sAcceptSocket,
  390.             (DWORD*)&AcceptSocket,
  391.             &Errno);
  392.  
  393.         if (SOCKET_ERROR != ReturnValue){
  394.             if (lpOverlapped) {
  395.                 if ((lpOverlapped->hEvent==NULL)
  396.                         || ResetEvent ((HANDLE)((DWORD)lpOverlapped->hEvent&0xFFFFFFFE))) {
  397.                     PDWORKERTHREAD  Thread = GetWorkerThread ();
  398.                     if (Thread!=NULL) {
  399.                         // Setup the user overlapped struct
  400.                         lpOverlapped->Internal = WSS_OPERATION_IN_PROGRESS;
  401.                         lpOverlapped->InternalHigh = 0;
  402.                         ReturnValue = Thread->QueueOverlappedAcceptEx(
  403.                                 ListenSocket,
  404.                                 AcceptSocket,
  405.                                 lpOutputBuffer,
  406.                                 dwReceiveDataLength,
  407.                                 dwLocalAddressLength,
  408.                                 dwRemoteAddressLength,
  409.                                 lpOverlapped,
  410.                                 &Errno);
  411.                     }
  412.                     else {
  413.                         ReturnValue = SOCKET_ERROR;
  414.                         Errno = WSAENOBUFS;
  415.                     }
  416.                 }
  417.                 else {
  418.                     ReturnValue = SOCKET_ERROR;
  419.                     Errno = WSA_INVALID_PARAMETER;
  420.                 }
  421.             }
  422.             else {
  423.                 Provider = ListenSocket->GetDProvider ();
  424.                 ProviderListenSocket = ListenSocket->GetProviderSocket ();
  425.                 ProviderAcceptSocket = AcceptSocket->GetProviderSocket ();
  426.  
  427.                 SetBlockingProvider (Provider);
  428.                 ReturnValue = Provider->AcceptEx (
  429.                         ProviderListenSocket,
  430.                         ProviderAcceptSocket,
  431.                         lpOutputBuffer,
  432.                         dwReceiveDataLength,
  433.                         dwLocalAddressLength,
  434.                         dwRemoteAddressLength,
  435.                         lpdwBytesReceived,
  436.                         lpOverlapped,
  437.                         &Errno);
  438.                 SetBlockingProvider (NULL);
  439.             }
  440.         }
  441.     }
  442.     if (ReturnValue==NO_ERROR)
  443.         return TRUE;
  444.     else {
  445.         SetLastError (Errno);
  446.         return FALSE;
  447.     }
  448. }
  449.  
  450.  
  451.  
  452.  
  453. INT
  454. WSPAPI
  455. WSPAddressToString(
  456.     IN     LPSOCKADDR lpsaAddress,
  457.     IN     DWORD dwAddressLength,
  458.     IN     LPWSAPROTOCOL_INFOW lpProtocolInfo,
  459.     OUT    LPWSTR lpszAddressString,
  460.     IN OUT LPDWORD lpdwAddressStringLength,
  461.     OUT    LPINT lpErrno )
  462. /*++
  463.  
  464. Routine Description:
  465.  
  466.     WSPAddressToString() converts a SOCKADDR structure into a human-readable
  467.     string representation of the address.  This is intended to be used mainly
  468.     for display purposes. If the caller wishes the translation to be done by a
  469.     particular provider, it should supply the corresponding WSAPROTOCOL_INFO
  470.     struct in the lpProtocolInfo parameter.
  471.  
  472. Arguments:
  473.  
  474.     lpsaAddress - points to a SOCKADDR structure to translate into a string.
  475.  
  476.     dwAddressLength - the length of the Address SOCKADDR.
  477.  
  478.     lpProtocolInfo - (optional) the WSAPROTOCOL_INFO struct for a particular
  479.                      provider.
  480.  
  481.     lpszAddressString - a buffer which receives the human-readable address
  482.                         string.
  483.  
  484.     lpdwAddressStringLength - on input, the length of the AddressString buffer.
  485.                               On output, returns the length of  the string
  486.                               actually copied into the buffer.
  487.  
  488. Return Value:
  489.  
  490.     The return value is 0 if the operation was successful.  Otherwise the value
  491.     SOCKET_ERROR is returned
  492. --*/
  493. {
  494.     INT                 ReturnValue;
  495.     PDPROVIDER          Provider;
  496.     PPROTO_CATALOG_ITEM BaseProviderCatalogEntry;
  497.  
  498.     if (PREAPINOTIFY(( DTCODE_WSPAddressToString,
  499.                        &ReturnValue,
  500.                        gLibraryName,
  501.                        &lpsaAddress,
  502.                        &dwAddressLength,
  503.                        &lpProtocolInfo,
  504.                        &lpszAddressString,
  505.                        &lpdwAddressStringLength,
  506.                        &lpErrno)) ){
  507.         return(ReturnValue);
  508.     } //if
  509.  
  510.     //
  511.     // Get the catlog entry for the next provider in the chain
  512.     //
  513.     ReturnValue = gProviderCatalog->FindNextProviderInChain(
  514.         lpProtocolInfo,
  515.         &Provider,
  516.         &BaseProviderCatalogEntry);
  517.  
  518.     if (NO_ERROR == ReturnValue){
  519.  
  520.         //
  521.         ReturnValue = Provider->WSPAddressToString(
  522.             lpsaAddress,
  523.             dwAddressLength,
  524.             BaseProviderCatalogEntry
  525.                 ? BaseProviderCatalogEntry->GetProtocolInfo()
  526.                 : lpProtocolInfo,
  527.             lpszAddressString,
  528.             lpdwAddressStringLength,
  529.             lpErrno);
  530.     } //if
  531.  
  532.     POSTAPINOTIFY(( DTCODE_WSPAddressToString,
  533.                     &ReturnValue,
  534.                     gLibraryName,
  535.                     &lpsaAddress,
  536.                     &dwAddressLength,
  537.                     &lpProtocolInfo,
  538.                     &lpszAddressString,
  539.                     &lpdwAddressStringLength,
  540.                     &lpErrno));
  541.  
  542.     return(ReturnValue);
  543. }
  544.  
  545.  
  546.  
  547.  
  548.  
  549. INT
  550. WSPAPI
  551. WSPAsyncSelect(
  552.     IN SOCKET s,
  553.     IN HWND hWnd,
  554.     IN unsigned int wMsg,
  555.     IN long lEvent,
  556.     OUT INT FAR *lpErrno
  557.     )
  558. /*++
  559. Routine Description:
  560.  
  561.     Request  Windows  message-based  event notification of network events for a
  562.     socket.
  563.  
  564. Arguments:
  565.  
  566.     s       - A  descriptor identiying a socket for which event notification is
  567.               required.
  568.  
  569.     hWnd    - A  handle  identifying  the window which should receive a message
  570.               when a network event occurs.
  571.  
  572.     wMsg    - The message to be sent when a network event occurs.
  573.  
  574.     lEvent  - bitmask  which specifies a combination of network events in which
  575.               the WinSock client is interested.
  576.  
  577.     lpErrno - A pointer to the error code.
  578.  
  579. Return Value:
  580.  
  581.     The  return  value  is 0 if the WinSock client's declaration of interest in
  582.     the  netowrk event set was successful.  Otherwise the value SOCKET_ERROR is
  583.     returned, and a specific error code is available in lpErrno.
  584.  
  585. --*/
  586. {
  587.     INT ReturnValue;
  588.     PDSOCKET     Socket;
  589.  
  590.     if (PREAPINOTIFY(( DTCODE_WSPAsyncSelect,
  591.                        &ReturnValue,
  592.                        gLibraryName,
  593.                        &s,
  594.                        &hWnd,
  595.                        &wMsg,
  596.                        &lEvent,
  597.                        &lpErrno)) ) {
  598.         return(ReturnValue);
  599.     }
  600.  
  601.     //
  602.     // Get our DSOCKET object
  603.     //
  604.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  605.         s,
  606.         (DWORD*)&Socket,
  607.         lpErrno);
  608.     if (SOCKET_ERROR != ReturnValue){
  609.         PDASYNCWINDOW   AsyncWindow = GetAsyncWindow ();
  610.         if (AsyncWindow!=NULL) {
  611.             Socket->RegisterAsyncOperation(
  612.                 hWnd,
  613.                 wMsg,
  614.                 lEvent);
  615.  
  616.             *lpErrno = NO_ERROR;
  617.             // Register this socket with the worker thread.
  618.             *lpErrno = AsyncWindow->RegisterSocket(Socket);
  619.  
  620.             if (NO_ERROR == *lpErrno){
  621.                 ReturnValue = NO_ERROR;
  622.             } //if
  623.             else{
  624.                 ReturnValue = SOCKET_ERROR;
  625.             } //else
  626.         }
  627.         else {
  628.             ReturnValue = SOCKET_ERROR;
  629.             *lpErrno = WSAENOBUFS;
  630.         }
  631.  
  632.     } //if
  633.  
  634.     POSTAPINOTIFY(( DTCODE_WSPAsyncSelect,
  635.                     &ReturnValue,
  636.                     gLibraryName,
  637.                     &s,
  638.                     &hWnd,
  639.                     &wMsg,
  640.                     &lEvent,
  641.                     &lpErrno));
  642.  
  643.     return(ReturnValue);
  644. }
  645.  
  646.  
  647.  
  648. INT
  649. WSPAPI
  650. WSPBind(
  651.     IN SOCKET s,
  652.     IN const struct sockaddr FAR *name,
  653.     IN INT namelen,
  654.     OUT INT FAR *lpErrno
  655.     )
  656. /*++
  657. Routine Description:
  658.  
  659.     Associate a local address (i.e. name) with a socket.
  660.  
  661. Arguments:
  662.  
  663.     s       - A descriptor identifying an unbound socket.
  664.  
  665.     name    - The  address  to assign to the socket.  The sockaddr structure is
  666.               defined as follows:
  667.  
  668.               struct sockaddr {
  669.                   u_short sa_family;
  670.                   char    sa_data[14];
  671.               };
  672.  
  673.               Except  for  the sa_family field,
  674. sockaddr contents are epxressed
  675.               in network byte order.
  676.  
  677.     namelen - The length of the name.
  678.  
  679.     lpErrno - A pointer to the error code.
  680.  
  681. Return Value:
  682.  
  683.     If   no   erro   occurs,  WSPBind()  returns  0.   Otherwise, it  returns
  684.     SOCKET_ERROR, and a specific error code is available in lpErrno.
  685.  
  686. --*/
  687. {
  688.     INT ReturnValue;
  689.     PDPROVIDER   Provider;
  690.     PDSOCKET     Socket;
  691.     SOCKET       ProviderSocket;
  692.  
  693.  
  694.     if (PREAPINOTIFY(( DTCODE_WSPBind,
  695.                        &ReturnValue,
  696.                        gLibraryName,
  697.                        &s,
  698.                        &name,
  699.                        &namelen,
  700.                        &lpErrno)) ) {
  701.  
  702.         return(ReturnValue);
  703.     }
  704.  
  705.     //
  706.     // Get our DSOCKET object
  707.     //
  708.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  709.         s,
  710.         (DWORD*)&Socket,
  711.         lpErrno);
  712.  
  713.     if (SOCKET_ERROR != ReturnValue){
  714.         Provider = Socket->GetDProvider();
  715.         ProviderSocket = Socket->GetProviderSocket();
  716.  
  717.         ReturnValue = Provider->WSPBind(
  718.             ProviderSocket,
  719.             name,
  720.             namelen,
  721.             lpErrno);
  722.  
  723.  
  724.         POSTAPINOTIFY(( DTCODE_WSPBind,
  725.                         &ReturnValue,
  726.                         gLibraryName,
  727.                         &s,
  728.                         &name,
  729.                         &namelen,
  730.                         &lpErrno));
  731.     }
  732.  
  733.     return(ReturnValue);
  734.  
  735. }
  736.  
  737.  
  738.  
  739. INT
  740. WSPAPI
  741. WSPCancelBlockingCall(OUT INT FAR *lpErrno)
  742. /*++
  743. Routine Description:
  744.  
  745.     Cancel a blocking call which is currently in progress.
  746.  
  747. Arguments:
  748.  
  749.     lpErrno - A pointer to the error code.
  750.  
  751. Return Value:
  752.  
  753.     The  value  returned  by  WSPCancelBlockingCall() is 0 if the operation was
  754.     successfully canceled.  Otherwise the value SOCKET_ERROR is returned,
  755. and a
  756.     specific error code is available in lpErrno.
  757.  
  758. --*/
  759. {
  760.       INT ReturnValue;
  761.       PDPROVIDER    Provider;
  762.  
  763.       if (PREAPINOTIFY(( DTCODE_WSPCancelBlockingCall,
  764.                          &ReturnValue,
  765.                          gLibraryName,
  766.                          &lpErrno)) ) {
  767.           return(ReturnValue);
  768.       }
  769.  
  770.       Provider = (PDPROVIDER)TlsGetValue (TlsIndex);
  771.       if (Provider!=NULL) {
  772.           ReturnValue = Provider->WSPCancelBlockingCall(
  773.               lpErrno);
  774.       }
  775.       else {
  776.           ReturnValue = SOCKET_ERROR;
  777.           *lpErrno = WSAEINVAL;
  778.       }
  779.  
  780.       POSTAPINOTIFY(( DTCODE_WSPCancelBlockingCall,
  781.                       &ReturnValue,
  782.                       gLibraryName,
  783.                       &lpErrno));
  784.  
  785.       return(ReturnValue);
  786. }
  787.  
  788.  
  789.  
  790. INT
  791. WSPAPI
  792. WSPCleanup(
  793.     OUT INT FAR *lpErrno
  794.     )
  795. /*++
  796. Routine Description:
  797.  
  798.     Terminate use of the WinSock service provider.
  799.  
  800. Arguments:
  801.  
  802.     lpErrno - A pointer to the error code.
  803.  
  804. Return Value:
  805.  
  806.     The  return  value  is  0 if the operation has been successfully initiated.
  807.     Otherwise  the  value SOCKET_ERROR is returned,
  808. and a specific error number
  809.     is available in lpErrno.
  810.  
  811. --*/
  812.  
  813. {
  814.     INT          ReturnValue;
  815.  
  816.     if (PREAPINOTIFY(( DTCODE_WSPCleanup,
  817.                        &ReturnValue,
  818.                        gLibraryName,
  819.                        &lpErrno)) ) {
  820.         return(ReturnValue);
  821.     }
  822.  
  823.     EnterCriticalSection(&gInitCriticalSection);
  824.     if (gStartupCount > 0){
  825.         gStartupCount--;
  826.         if (gStartupCount == 0){
  827.  
  828.             DEBUGF( DBG_TRACE,
  829.                     ("Tearing down layered provider\n"));
  830.  
  831.             if (gAsyncWindow!=UNINITIALIZED_WINDOW) {
  832.                 if (gAsyncWindow!=NULL)
  833.                     //Kill the worker thread
  834.                     gAsyncWindow->Destroy ();
  835.                 gAsyncWindow = UNINITIALIZED_WINDOW;
  836.             }
  837.  
  838.             if (gWorkerThread!=UNINITIALIZED_THREAD) {
  839.                 if (gWorkerThread!=NULL)
  840.                     //Kill the worker thread
  841.                     gWorkerThread->Destroy ();
  842.                 gWorkerThread = UNINITIALIZED_THREAD;
  843.             }
  844.  
  845.             // To let threads wake up and figure out that
  846.             // they being cleaned up
  847.             Sleep (100);
  848.  
  849.             DSOCKET::DSocketClassCleanup ();
  850.  
  851.             // Kill the ProviderCatalog
  852.             delete(gProviderCatalog);
  853.  
  854.             //Kill the buffer manager
  855.             delete(gBufferManager);
  856.             DEBUGF( DBG_TRACE,
  857.                     ("Tearing down Complete\n"));
  858.  
  859.         } //if
  860.     } //if
  861.     ReturnValue = NO_ERROR;
  862.     *lpErrno = NO_ERROR;
  863.  
  864.     LeaveCriticalSection(&gInitCriticalSection);
  865.  
  866.     POSTAPINOTIFY(( DTCODE_WSPCleanup,
  867.                     &ReturnValue,
  868.                     gLibraryName,
  869.                     &lpErrno));
  870.  
  871.     return(ReturnValue);
  872.  
  873. }
  874.  
  875.  
  876.  
  877. INT
  878. WSPAPI
  879. WSPCloseSocket(
  880.     IN SOCKET s,
  881.     OUT INT FAR *lpErrno
  882.     )
  883. /*++
  884. Routine Description:
  885.  
  886.     Close a socket.
  887.  
  888. Arguments:
  889.  
  890.     s       - A descriptor identifying a socket.
  891.  
  892.     lpErrno - A pointer to the error code.
  893.  
  894. Return Value:
  895.  
  896.     If  no  erro  occurs, WSPCloseSocket()  returns  0.  Otherwise, a value of
  897.     SOCKET_ERROR  is  returned,  and  a  specific  error  code  is available in
  898.     lpErrno.
  899.  
  900. --*/
  901. {
  902.     INT ReturnValue;
  903.     PDSOCKET     Socket;
  904.     PDPROVIDER   Provider;
  905.     SOCKET       ProviderSocket;
  906.  
  907.  
  908.     if (PREAPINOTIFY(( DTCODE_WSPCloseSocket,
  909.                        &ReturnValue,
  910.                        gLibraryName,
  911.                        &s,
  912.                        &lpErrno)) ) {
  913.         return(ReturnValue);
  914.     }
  915.  
  916.     //
  917.     // Get our DSOCKET object
  918.     //
  919.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  920.         s,
  921.         (DWORD*)&Socket,
  922.         lpErrno);
  923.     if (SOCKET_ERROR != ReturnValue){
  924.         Provider = Socket->GetDProvider();
  925.         ProviderSocket = Socket->GetProviderSocket();
  926.         DEBUGF( DBG_TRACE,
  927.                 ("Closing socket %X\n",s));
  928.  
  929.         Socket->Remove ();
  930.  
  931.         ReturnValue = Provider->WSPCloseSocket(
  932.             ProviderSocket,
  933.             lpErrno);
  934.  
  935.         if (NO_ERROR==ReturnValue) {
  936.             gUpCallTable.lpWPUCloseSocketHandle(
  937.                 Socket->GetSocketHandle(),
  938.                 lpErrno);
  939.  
  940.             delete(Socket);
  941.  
  942.             ReturnValue = NO_ERROR;
  943.         }
  944.     } //if
  945.  
  946.  
  947.     POSTAPINOTIFY(( DTCODE_WSPCloseSocket,
  948.                     &ReturnValue,
  949.                     gLibraryName,
  950.                     &s,
  951.                     &lpErrno));
  952.  
  953.     return(ReturnValue);
  954.  
  955. }
  956.  
  957.  
  958.  
  959. INT
  960. WSPAPI
  961. WSPConnect(
  962.     IN SOCKET s,
  963.     IN const struct sockaddr FAR *name,
  964.     IN INT namelen,
  965.     IN LPWSABUF lpCallerData,
  966.     IN LPWSABUF lpCalleeData,
  967.     IN LPQOS lpSQOS,
  968.     IN LPQOS lpGQOS,
  969.     OUT INT FAR *lpErrno
  970.     )
  971. /*++
  972. Routine Description:
  973.  
  974.     Establish a connection to a peer,
  975. exchange connect data,
  976. and specify needed
  977.     quality of service based on the supplied flow spec.
  978.  
  979. Arguments:
  980.  
  981.     s            - A descriptor identifying an unconnected socket.
  982.  
  983.     name         - The name of the peer to which the socket is to be connected.
  984.  
  985.     namelen      - The length of the name.
  986.  
  987.     lpCallerData - A  pointer to the user data that is to be transferred to the
  988.                    peer during connection established.
  989.  
  990.     lpCalleeData - A pointer to a buffer into which may be copied any user data
  991.                    received from the peer during connection establishment.
  992.  
  993.     lpSQOS       - A  pointer  to  the  flow  specs  for socket s, one for each
  994.                    direction.
  995.  
  996.     lpGQOS       - A  pointer  to  the  flow  specs  for  the  socket group (if
  997.                    applicable).
  998.  
  999.     lpErrno      - A pointer to the error code.
  1000.  
  1001. Return Value:
  1002.  
  1003.     If  no  error  occurs, WSPConnect()  returns NO_ERROR.  Otherwise, it
  1004.     returns SOCKET_ERROR, and a specific erro rcode is available in lpErrno.
  1005.  
  1006. --*/
  1007. {
  1008.     INT ReturnValue;
  1009.     PDSOCKET     Socket;
  1010.     PDPROVIDER   Provider;
  1011.     SOCKET       ProviderSocket;
  1012.  
  1013.     if (PREAPINOTIFY(( DTCODE_WSPConnect,
  1014.                        &ReturnValue,
  1015.                        gLibraryName,
  1016.                        &s,
  1017.                        &name,
  1018.                        &namelen,
  1019.                        &lpCallerData,
  1020.                        &lpCalleeData,
  1021.                        &lpSQOS,
  1022.                        &lpGQOS,
  1023.                        &lpErrno)) ) {
  1024.         return(ReturnValue);
  1025.     }
  1026.  
  1027.     //
  1028.     // Get our DSOCKET object
  1029.     //
  1030.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  1031.         s,
  1032.         (DWORD*)&Socket,
  1033.         lpErrno);
  1034.     if (SOCKET_ERROR != ReturnValue){
  1035.         Provider = Socket->GetDProvider();
  1036.         ProviderSocket = Socket->GetProviderSocket();
  1037.  
  1038.         SetBlockingProvider (Provider);
  1039.         ReturnValue = Provider->WSPConnect(
  1040.             ProviderSocket,
  1041.             name,
  1042.             namelen,
  1043.             lpCallerData,
  1044.             lpCalleeData,
  1045.             lpSQOS,
  1046.             lpGQOS,
  1047.             lpErrno);
  1048.         SetBlockingProvider (NULL);
  1049.     }//if
  1050.  
  1051.     POSTAPINOTIFY(( DTCODE_WSPConnect,
  1052.                     &ReturnValue,
  1053.                     gLibraryName,
  1054.                     &s,
  1055.                     &name,
  1056.                     &namelen,
  1057.                     &lpCallerData,
  1058.                     &lpCalleeData,
  1059.                     &lpSQOS,
  1060.                     &lpGQOS,
  1061.                     &lpErrno));
  1062.  
  1063.     return(ReturnValue);
  1064.  
  1065. }
  1066.  
  1067.  
  1068.  
  1069. INT
  1070. WSPAPI
  1071. WSPDuplicateSocket(
  1072.     IN SOCKET s,
  1073.     IN DWORD dwProcessID,
  1074.     OUT LPWSAPROTOCOL_INFOW lpProtocolInfo,
  1075.     OUT INT FAR *lpErrno
  1076.     )
  1077. /*++
  1078. Routine Description:
  1079.  
  1080.     descriptor for a shared socket.
  1081.  
  1082.  
  1083. Arguments:
  1084.  
  1085.     s              - Specifies the local socket descriptor.
  1086.  
  1087.     dwProcessID    - Specifies  the  ID  of  the  target  process for which the
  1088.                      shared socket will be used.
  1089.  
  1090.     lpProtocolInfo - A  pointer  to  a  buffer  allocated by the client that is
  1091.                      large enough to contain a WSAPROTOCOL_INFOA struct.  The
  1092.                      service  provider copies the protocol info struct contents
  1093.                      to this buffer.
  1094.  
  1095.     lpErrno        - A pointer to the error code
  1096.  
  1097. Return Value:
  1098.  
  1099.     If  no  error  occurs, WPSDuplicateSocket()  returns zero.  Otherwise, the
  1100.     value of SOCKET_ERROR is returned, and a specific error number is available
  1101.     in lpErrno.
  1102.  
  1103. --*/
  1104. {
  1105.     INT                    ReturnValue=SOCKET_ERROR;
  1106.     PDPROVIDER            Provider;
  1107.     PDSOCKET            Socket;
  1108.     SOCKET                ProviderSocket;
  1109.     PPROTO_CATALOG_ITEM    ChainCatalogItem;
  1110.     DWORD                Reserved;
  1111.  
  1112.     if (PREAPINOTIFY(( DTCODE_WSPDuplicateSocket,
  1113.                      &ReturnValue,
  1114.                      gLibraryName,
  1115.                      &s,
  1116.                      &dwProcessID,
  1117.                      &lpProtocolInfo,
  1118.                      &lpErrno)) ) {
  1119.       return(ReturnValue);
  1120.     }
  1121.  
  1122.  
  1123.     //
  1124.     // Get our DSOCKET object
  1125.     //
  1126.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  1127.         s,
  1128.         (DWORD*)&Socket,
  1129.         lpErrno);
  1130.     if (SOCKET_ERROR != ReturnValue){
  1131.         // Get chain catalog entry 
  1132.         ReturnValue = gProviderCatalog->GetCatalogItemFromCatalogEntryId(
  1133.                 Socket->GetCatalogEntryId(),
  1134.                 &ChainCatalogItem);
  1135.         if (NO_ERROR==ReturnValue) {
  1136.             // Call next provider to duplicate its socket
  1137.             Provider = Socket->GetDProvider();
  1138.             ProviderSocket = Socket->GetProviderSocket();
  1139.  
  1140.             ReturnValue = Provider->WSPDuplicateSocket(
  1141.                 ProviderSocket,
  1142.                 dwProcessID,
  1143.                 lpProtocolInfo,
  1144.                 lpErrno);
  1145.             if (NO_ERROR==ReturnValue) {
  1146.                 // Replace returned protocol infor
  1147.                 // with chain protocol info and
  1148.                 // carefully restore provider reserved field.
  1149.                 Reserved = lpProtocolInfo->dwProviderReserved;
  1150.                 *lpProtocolInfo = *ChainCatalogItem->GetProtocolInfo ();
  1151.                 lpProtocolInfo->dwProviderReserved = Reserved;
  1152.             }
  1153.  
  1154.  
  1155.         } // if
  1156.     } //if
  1157.  
  1158.     POSTAPINOTIFY(( DTCODE_WSPDuplicateSocket,
  1159.                   &ReturnValue,
  1160.                   gLibraryName,
  1161.                   &s,
  1162.                   &dwProcessID,
  1163.                   &lpProtocolInfo,
  1164.                   &lpErrno));
  1165.  
  1166.     return(ReturnValue);
  1167.  
  1168. }
  1169.  
  1170.  
  1171.  
  1172. INT
  1173. WSPAPI
  1174. WSPEnumNetworkEvents(
  1175.     IN SOCKET s,
  1176.     OUT WSAEVENT hEventObject,
  1177.     OUT LPWSANETWORKEVENTS lpNetworkEvents,
  1178.     OUT INT FAR *lpErrno
  1179.     )
  1180. /*++
  1181. Routine Description:
  1182.  
  1183.     Report occurrences of network events for the indicated socket.
  1184.  
  1185. Arguments:
  1186.  
  1187.     s               - A descriptor identifying the socket.
  1188.  
  1189.     hEventObject    - An optional handle identifying an associated event object
  1190.                       to be reset.
  1191.  
  1192.     lpNetworkEvents - A  pointer  to  a WSANETWORKEVENTS struct which is filled
  1193.                       with   a  record  of  occurred  network  events  and  any
  1194.                       associated error codes.
  1195.  
  1196.     lpErrno         - A pointer to the error code.
  1197.  
  1198. Return Value:
  1199.  
  1200.     The  return  value  is  NO_ERROR  if  the  operation  was  successful.
  1201.     Otherwise  the  value SOCKET_ERROR is returned, and a specific error number
  1202.     is available in lpErrno.
  1203.  
  1204. --*/
  1205. {
  1206.     INT ReturnValue;
  1207.     PDSOCKET     Socket;
  1208.     PDPROVIDER   Provider;
  1209.     SOCKET       ProviderSocket;
  1210.  
  1211.     if (PREAPINOTIFY(( DTCODE_WSPEnumNetworkEvents,
  1212.                        &ReturnValue,
  1213.                        gLibraryName,
  1214.                        &s,
  1215.                        &hEventObject,
  1216.                        &lpNetworkEvents,
  1217.                        &lpErrno)) ) {
  1218.         return(ReturnValue);
  1219.     }
  1220.  
  1221.     //
  1222.     // Get our DSOCKET object
  1223.     //
  1224.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  1225.         s,
  1226.         (DWORD*)&Socket,
  1227.         lpErrno);
  1228.     if (SOCKET_ERROR != ReturnValue){
  1229.         Provider = Socket->GetDProvider();
  1230.         ProviderSocket = Socket->GetProviderSocket();
  1231.  
  1232.         ReturnValue = Provider->WSPEnumNetworkEvents(
  1233.             ProviderSocket,
  1234.             hEventObject,
  1235.             lpNetworkEvents,
  1236.             lpErrno);
  1237.     } //if
  1238.  
  1239.     POSTAPINOTIFY(( DTCODE_WSPEnumNetworkEvents,
  1240.                     &ReturnValue,
  1241.                     gLibraryName,
  1242.                     &s,
  1243.                     &hEventObject,
  1244.                     &lpNetworkEvents,
  1245.                     &lpErrno));
  1246.  
  1247.     return(ReturnValue);
  1248.  
  1249. }
  1250.  
  1251.  
  1252.  
  1253. INT
  1254. WSPAPI
  1255. WSPEventSelect(
  1256.     IN SOCKET s,
  1257.     IN OUT WSAEVENT hEventObject,
  1258.     IN long lNetworkEvents,
  1259.     OUT INT FAR *lpErrno
  1260.     )
  1261. /*++
  1262. Routine Description:
  1263.  
  1264.     Specify  an  event object to be associated with the supplied set of network
  1265.     events.
  1266.  
  1267. Arguments:
  1268.  
  1269.     s              - A descriptor identifying the socket.
  1270.  
  1271.     hEventObject   - A  handle  identifying  the  event object to be associated
  1272.                      with the supplied set of network events.
  1273.  
  1274.     lNetworkEvents - A  bitmask  which  specifies  the  combination  of network
  1275.                      events in which the WinSock client has interest.
  1276.  
  1277.     lpErrno        - A pointer to the error code.
  1278.  
  1279. Return Value:
  1280.  
  1281.     The return value is 0 if the WinSock client's specification of the network
  1282.     events and the associated event object was successful. Otherwise the value
  1283.     SOCKET_ERROR is returned, and a specific error number is available in
  1284.     lpErrno
  1285.  
  1286. --*/
  1287. {
  1288.     INT ReturnValue;
  1289.     PDSOCKET     Socket;
  1290.     PDPROVIDER   Provider;
  1291.     SOCKET       ProviderSocket;
  1292.  
  1293.  
  1294.     if (PREAPINOTIFY(( DTCODE_WSPEventSelect,
  1295.                        &ReturnValue,
  1296.                        gLibraryName,
  1297.                        &s,
  1298.                        &hEventObject,
  1299.                        &lNetworkEvents,
  1300.                        &lpErrno)) ) {
  1301.         return(ReturnValue);
  1302.     }
  1303.  
  1304.     //
  1305.     // Get our DSOCKET object
  1306.     //
  1307.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  1308.         s,
  1309.         (DWORD*)&Socket,
  1310.         lpErrno);
  1311.     if (SOCKET_ERROR != ReturnValue){
  1312.         Provider = Socket->GetDProvider();
  1313.         ProviderSocket = Socket->GetProviderSocket();
  1314.  
  1315.         ReturnValue = Provider->WSPEventSelect(
  1316.             ProviderSocket,
  1317.             hEventObject,
  1318.             lNetworkEvents,
  1319.             lpErrno);
  1320.     } //if
  1321.  
  1322.     POSTAPINOTIFY(( DTCODE_WSPEventSelect,
  1323.                     &ReturnValue,
  1324.                     gLibraryName,
  1325.                     &s,
  1326.                     &hEventObject,
  1327.                     &lNetworkEvents,
  1328.                     &lpErrno));
  1329.  
  1330.     return(ReturnValue);
  1331.  
  1332. }
  1333.  
  1334.  
  1335.  
  1336. INT
  1337. WSPAPI
  1338. WSPGetOverlappedResult(
  1339.     IN SOCKET s,
  1340.     IN LPWSAOVERLAPPED lpOverlapped,
  1341.     IN LPDWORD lpcbTransfer,
  1342.     IN BOOL fWait,
  1343.     OUT LPDWORD lpdwFlags,
  1344.     OUT INT FAR *lpErrno
  1345.     )
  1346. /*++
  1347. Routine Description:
  1348.  
  1349.     Returns the results of an overlapped operation on the specified socket.
  1350.  
  1351. Arguments:
  1352.  
  1353.     s            - Identifies  the  socket.   This  is the same socket that was
  1354.                    specified  when  the  overlapped  operation was started by a
  1355.                    call to WSPRecv(), WSPRecvFrom(), WSPSend(), WSPSendTo(), or
  1356.                    WSPIoctl().
  1357.  
  1358.     lpOverlapped - Points to a WSAOVERLAPPED structure that was specified
  1359.                    when the overlapped operation was started.
  1360.  
  1361.     lpcbTransfer - Points to a 32-bit variable that receives the number of
  1362.                    bytes that were actually transferred by a send or receive
  1363.                    operation, or by WSPIoctl().
  1364.  
  1365.     fWait        - Specifies  whether  the function should wait for the pending
  1366.                    overlapped  operation  to  complete.   If TRUE, the function
  1367.                    does  not return until the operation has been completed.  If
  1368.                    FALSE  and  the  operation  is  still  pending, the function
  1369.                    returns FALSE and lperrno is WSA_IO_INCOMPLETE.
  1370.  
  1371.     lpdwFlags    - Points  to  a  32-bit variable that will receive one or more
  1372.                    flags   that  supplement  the  completion  status.   If  the
  1373.                    overlapped   operation   was   initiated  via  WSPRecv()  or
  1374.                    WSPRecvFrom(), this parameter will contain the results value
  1375.                    for lpFlags parameter.
  1376.  
  1377.     lpErrno      - A pointer to the error code.
  1378.  
  1379. Return Value:
  1380.  
  1381.     If WSPGetOverlappedResult() succeeds,the return value is TRUE.  This means
  1382.     that the overlapped operation has completed successfully and that the value
  1383.     pointed  to  by lpcbTransfer has been updated.  If WSPGetOverlappedResult()
  1384.     returns  FALSE,  this  means  that  either the overlapped operation has not
  1385.     completed  or  the  overlapped operation completed but with errors, or that
  1386.     completion  status  could  not  be  determined due to errors in one or more
  1387.     parameters  to  WSPGetOverlappedResult().  On failure, the value pointed to
  1388.     by  lpcbTransfer  will  not be updated.  lpErrno indicates the cause of the
  1389.     failure (either of WSPGetOverlappedResult() or of the associated overlapped
  1390.     operation).
  1391.  
  1392. --*/
  1393. {
  1394.     INT ReturnValue;
  1395.  
  1396.     if (PREAPINOTIFY(( DTCODE_WSPGetOverlappedResult,
  1397.                        &ReturnValue,
  1398.                        gLibraryName,
  1399.                        &s,
  1400.                        &lpOverlapped,
  1401.                        &lpcbTransfer,
  1402.                        &fWait,
  1403.                        &lpdwFlags,
  1404.                        &lpErrno)) ) {
  1405.         return(ReturnValue);
  1406.     }
  1407.  
  1408.     if (lpOverlapped->Internal!=WSS_OPERATION_IN_PROGRESS) {
  1409.         *lpcbTransfer = lpOverlapped->InternalHigh;
  1410.         *lpdwFlags = lpOverlapped->Offset;
  1411.         *lpErrno = lpOverlapped->OffsetHigh;
  1412.         ReturnValue = lpOverlapped->OffsetHigh==0;
  1413.     }
  1414.     else if (fWait) {
  1415.         ReturnValue = WaitForSingleObject (lpOverlapped->hEvent, INFINITE);
  1416.         if ((ReturnValue==WAIT_OBJECT_0) 
  1417.                 && (lpOverlapped->Internal!=WSS_OPERATION_IN_PROGRESS)) {
  1418.             *lpcbTransfer = lpOverlapped->InternalHigh;
  1419.             *lpdwFlags = lpOverlapped->Offset;
  1420.             *lpErrno = lpOverlapped->OffsetHigh;
  1421.             ReturnValue = lpOverlapped->OffsetHigh==0;
  1422.         }
  1423.         else {
  1424.             ReturnValue = FALSE;
  1425.             *lpErrno = WSASYSCALLFAILURE;
  1426.         }
  1427.     }
  1428.     else {
  1429.         *lpErrno = WSA_IO_PENDING;
  1430.         ReturnValue = FALSE;
  1431.     }
  1432.  
  1433.     POSTAPINOTIFY(( DTCODE_WSPGetOverlappedResult,
  1434.                     &ReturnValue,
  1435.                     gLibraryName,
  1436.                     &s,
  1437.                     &lpOverlapped,
  1438.                     &lpcbTransfer,
  1439.                     &fWait,
  1440.                     &lpdwFlags,
  1441.                     &lpErrno));
  1442.  
  1443.     return(ReturnValue);
  1444. }
  1445.  
  1446.  
  1447.  
  1448. INT
  1449. WSPAPI
  1450. WSPGetPeerName(
  1451.     IN SOCKET s,
  1452.     OUT struct sockaddr FAR *name,
  1453.     OUT INT FAR *namelen,
  1454.     OUT INT FAR *lpErrno
  1455.     )
  1456. /*++
  1457. Routine Description:
  1458.  
  1459.     Get the address of the peer to which a socket is connected.
  1460.  
  1461. Arguments:
  1462.  
  1463.     s       - A descriptor identifying a connected socket.
  1464.  
  1465.     name    - A  pointer  to  the structure which is to receive the name of the
  1466.               peer.
  1467.  
  1468.     namelen - A  pointer  to  an integer which, on input, indicates the size of
  1469.               the  structure  pointed  to  by name, and on output indicates the
  1470.               size of the returned name.
  1471.  
  1472.     lpErrno - A pointer to the error code.
  1473.  
  1474. Return Value:
  1475.  
  1476.     If  no  error occurs, WSPGetPeerName() returns NO_ERROR.  Otherwise, a
  1477.     value  of  SOCKET_ERROR is returned, and a specific error code is available
  1478.     in lpErrno
  1479.  
  1480. --*/
  1481. {
  1482.     INT ReturnValue;
  1483.     PDSOCKET     Socket;
  1484.     PDPROVIDER   Provider;
  1485.     SOCKET       ProviderSocket;
  1486.  
  1487.  
  1488.     if (PREAPINOTIFY(( DTCODE_WSPGetPeerName,
  1489.                        &ReturnValue,
  1490.                        gLibraryName,
  1491.                        &s,
  1492.                        &name,
  1493.                        &namelen,
  1494.                        &lpErrno)) ) {
  1495.         return(ReturnValue);
  1496.     }
  1497.  
  1498.     //
  1499.     // Get our DSOCKET object
  1500.     //
  1501.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  1502.         s,
  1503.         (DWORD*)&Socket,
  1504.         lpErrno);
  1505.     if (SOCKET_ERROR != ReturnValue){
  1506.         Provider = Socket->GetDProvider();
  1507.         ProviderSocket = Socket->GetProviderSocket();
  1508.  
  1509.         ReturnValue = Provider->WSPGetPeerName(
  1510.         ProviderSocket,
  1511.         name,
  1512.         namelen,
  1513.         lpErrno);
  1514.  
  1515.     } //if
  1516.  
  1517.     POSTAPINOTIFY(( DTCODE_WSPGetPeerName,
  1518.                     &ReturnValue,
  1519.                     gLibraryName,
  1520.                     &s,
  1521.                     &name,
  1522.                     &namelen,
  1523.                     &lpErrno));
  1524.  
  1525.     return(ReturnValue);
  1526. }
  1527.  
  1528.  
  1529.  
  1530. INT
  1531. WSPAPI
  1532. WSPGetQOSByName(
  1533.     IN SOCKET s,
  1534.     IN LPWSABUF lpQOSName,
  1535.     IN LPQOS lpQOS,
  1536.     OUT INT FAR *lpErrno
  1537.     )
  1538. /*++
  1539. Routine Description:
  1540.  
  1541.     Initializes a QOS structure based on a named template.
  1542.  
  1543. Arguments:
  1544.  
  1545.     s         - A descriptor identifying a socket.
  1546.  
  1547.     lpQOSName - Specifies the QOS template name.
  1548.  
  1549.     lpQOS     - A pointer to the QOS structure to be filled.
  1550.  
  1551.     lpErrno   - A pointer to the error code.
  1552.  
  1553. Return Value:
  1554.  
  1555.     If the function succeeds, the return value is TRUE.  If the function fails,
  1556.     the  return  value  is  FALSE, and  a  specific error code is available in
  1557.     lpErrno.
  1558.  
  1559. --*/
  1560. {
  1561.     INT ReturnValue;
  1562.     PDSOCKET     Socket;
  1563.     PDPROVIDER   Provider;
  1564.     SOCKET       ProviderSocket;
  1565.  
  1566.  
  1567.     if (PREAPINOTIFY(( DTCODE_WSPGetQOSByName,
  1568.                        &ReturnValue,
  1569.                        gLibraryName,
  1570.                        &s,
  1571.                        &lpQOSName,
  1572.                        &lpQOS,
  1573.                        &lpErrno)) ) {
  1574.         return(ReturnValue);
  1575.     }
  1576.  
  1577.     //
  1578.     // Get our DSOCKET object
  1579.     //
  1580.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  1581.         s,
  1582.         (DWORD*)&Socket,
  1583.         lpErrno);
  1584.     if (SOCKET_ERROR != ReturnValue){
  1585.         Provider = Socket->GetDProvider();
  1586.         ProviderSocket = Socket->GetProviderSocket();
  1587.  
  1588.         ReturnValue = Provider->WSPGetQOSByName(
  1589.             ProviderSocket,
  1590.             lpQOSName,
  1591.             lpQOS,
  1592.             lpErrno);
  1593.     } //if
  1594.  
  1595.     POSTAPINOTIFY(( DTCODE_WSPGetQOSByName,
  1596.                     &ReturnValue,
  1597.                     gLibraryName,
  1598.                     &s,
  1599.                     &lpQOSName,
  1600.                     &lpQOS,
  1601.                     &lpErrno));
  1602.  
  1603.     return(ReturnValue);
  1604. }
  1605.  
  1606.  
  1607.  
  1608. INT
  1609. WSPAPI
  1610. WSPGetSockName(
  1611.     IN SOCKET s,
  1612.     OUT struct sockaddr FAR *name,
  1613.     OUT INT FAR *namelen,
  1614.     OUT INT FAR *lpErrno
  1615.     )
  1616. /*++
  1617. Routine Description:
  1618.  
  1619.     Get the local name for a socket.
  1620.  
  1621. Arguments:
  1622.  
  1623.     s       - A descriptor identifying a bound socket.
  1624.  
  1625.     name    - A pointer to a structure used to supply the address (name) of the
  1626.               socket.
  1627.  
  1628.     namelen - A  pointer  to  an integer which, on input, indicates the size of
  1629.               the  structure  pointed  to  by name, and on output indicates the
  1630.               size of the returned name
  1631.  
  1632.     lpErrno - A Pointer to the error code.
  1633.  
  1634. Return Value:
  1635.  
  1636.     If  no  error occurs, WSPGetSockName() returns NO_ERROR.  Otherwise, a
  1637.     value  of  SOCKET_ERROR is returned, and a specific error code is available
  1638.     in lpErrno.
  1639.  
  1640. --*/
  1641. {
  1642.     INT ReturnValue;
  1643.     PDSOCKET     Socket;
  1644.     PDPROVIDER   Provider;
  1645.     SOCKET       ProviderSocket;
  1646.  
  1647.  
  1648.     if (PREAPINOTIFY(( DTCODE_WSPGetSockName,
  1649.                        &ReturnValue,
  1650.                        gLibraryName,
  1651.                        &s,
  1652.                        &name,
  1653.                        &namelen,
  1654.                        &lpErrno)) ) {
  1655.         return(ReturnValue);
  1656.     }
  1657.  
  1658.     //
  1659.     // Get our DSOCKET object
  1660.     //
  1661.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  1662.         s,
  1663.         (DWORD*)&Socket,
  1664.         lpErrno);
  1665.     if (SOCKET_ERROR != ReturnValue){
  1666.         Provider = Socket->GetDProvider();
  1667.         ProviderSocket = Socket->GetProviderSocket();
  1668.  
  1669.         ReturnValue = Provider->WSPGetSockName(
  1670.             ProviderSocket,
  1671.             name,
  1672.             namelen,
  1673.             lpErrno);
  1674.     } //if
  1675.  
  1676.     POSTAPINOTIFY(( DTCODE_WSPGetSockName,
  1677.                     &ReturnValue,
  1678.                     gLibraryName,
  1679.                     &s,
  1680.                     &name,
  1681.                     &namelen,
  1682.                     &lpErrno));
  1683.  
  1684.     return(ReturnValue);
  1685. }
  1686.  
  1687.  
  1688.  
  1689.  INT
  1690. WSPAPI
  1691. WSPGetSockOpt(
  1692.     IN SOCKET s,
  1693.     IN INT level,
  1694.     IN INT optname,
  1695.     OUT char FAR *optval,
  1696.     OUT INT FAR *optlen,
  1697.     OUT INT FAR *lpErrno
  1698.     )
  1699. /*++
  1700. Routine Description:
  1701.  
  1702.     Retrieve a socket option.
  1703.  
  1704. Arguments:
  1705.  
  1706.     s       - A descriptor identifying a socket.
  1707.  
  1708.     level   - The  level  at  which the option is defined; the supported levels
  1709.               include SOL_SOCKET (See annex for more protocol-specific levels.)
  1710.  
  1711.     optname - The socket option for which the value is to be retrieved.
  1712.  
  1713.     optval  - A  pointer  to  the  buffer  in which the value for the requested
  1714.               option is to be returned.
  1715.  
  1716.     optlen  - A pointer to the size of the optval buffer.
  1717.  
  1718.     lpErrno - A pointer to the error code.
  1719.  
  1720. Return Value:
  1721.  
  1722.     If  no  error  occurs,  WSPGetSockOpt()  returns  0.  Otherwise, a value of
  1723.     SOCKET_ERROR  is  returned,  and  a  specific  error  code  is available in
  1724.     lpErrno.
  1725.  
  1726. --*/
  1727. {
  1728.     INT ReturnValue;
  1729.     PDSOCKET     Socket;
  1730.     PDPROVIDER   Provider;
  1731.     SOCKET       ProviderSocket;
  1732.  
  1733.  
  1734.     if (PREAPINOTIFY(( DTCODE_WSPGetSockOpt,
  1735.                        &ReturnValue,
  1736.                        gLibraryName,
  1737.                        &s,
  1738.                        &level,
  1739.                        &optname,
  1740.                        &optval,
  1741.                        &optlen,
  1742.                        &lpErrno)) ) {
  1743.         return(ReturnValue);
  1744.     }
  1745.  
  1746.     //
  1747.     // Get our DSOCKET object
  1748.     //
  1749.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  1750.         s,
  1751.         (DWORD*)&Socket,
  1752.         lpErrno);
  1753.     if (SOCKET_ERROR != ReturnValue){
  1754.         Provider = Socket->GetDProvider();
  1755.         ProviderSocket = Socket->GetProviderSocket();
  1756.  
  1757.         ReturnValue = Provider->WSPGetSockOpt(
  1758.             ProviderSocket,
  1759.             level,
  1760.             optname,
  1761.             optval,
  1762.             optlen,
  1763.             lpErrno);
  1764.     } //if
  1765.  
  1766.     POSTAPINOTIFY(( DTCODE_WSPGetSockOpt,
  1767.                     &ReturnValue,
  1768.                     gLibraryName,
  1769.                     &s,
  1770.                     &level,
  1771.                     &optname,
  1772.                     &optval,
  1773.                     &optlen,
  1774.                     &lpErrno));
  1775.  
  1776.     return(ReturnValue);
  1777. }
  1778.  
  1779.  
  1780. INT
  1781. WSPAPI
  1782. WSPIoctl(
  1783.     IN SOCKET s,
  1784.     IN DWORD dwIoControlCode,
  1785.     IN LPVOID lpvInBuffer,
  1786.     IN DWORD cbInBuffer,
  1787.     IN LPVOID lpvOutBuffer,
  1788.     IN DWORD cbOutBuffer,
  1789.     IN LPDWORD lpcbBytesReturned,
  1790.     IN LPWSAOVERLAPPED lpOverlapped,
  1791.     IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  1792.     IN LPWSATHREADID lpThreadId,
  1793.     OUT INT FAR *lpErrno
  1794.     )
  1795. /*++
  1796. Routine Description:
  1797.  
  1798.     Control the mode of a socket.
  1799.  
  1800. Arguments:
  1801.  
  1802.     s                   - Handle to a socket
  1803.  
  1804.     dwIoControlCode     - Control code of operation to perform
  1805.  
  1806.     lpvInBuffer         - Address of input buffer
  1807.  
  1808.     cbInBuffer          - Size of input buffer
  1809.  
  1810.     lpvOutBuffer        - Address of output buffer
  1811.  
  1812.     cbOutBuffer         - Size of output buffer
  1813.  
  1814.     lpcbBytesReturned   - A pointer to the size of output buffer's contents.
  1815.  
  1816.     lpOverlapped        - Address of WSAOVERLAPPED structure
  1817.  
  1818.     lpCompletionRoutine - A  pointer  to the completion routine called when the
  1819.                           operation has been completed.
  1820.  
  1821.     lpThreadId          - A  pointer to a thread ID structure to be used by the
  1822.                           provider
  1823.  
  1824.     lpErrno             - A pointer to the error code.
  1825.  
  1826. Return Value:
  1827.  
  1828.     If  no error occurs and the operation has completed immediately, WSPIoctl()
  1829.     returns  0.   Note  that in this case the completion routine, if specified,
  1830.     will  have  already  been  queued.   Otherwise, a value of SOCKET_ERROR is
  1831.     returned, and  a  specific  error code is available in lpErrno.  The error
  1832.     code  WSA_IO_PENDING  indicates  that  an  overlapped  operation  has  been
  1833.     successfully  initiated  and  that  conpletion will be indicated at a later
  1834.     time.   Any  other  error  code  indicates that no overlapped operation was
  1835.     initiated and no completion indication will occur.
  1836.  
  1837. --*/
  1838. {
  1839.     INT ReturnValue;
  1840.     PDSOCKET     Socket;
  1841.     PDPROVIDER   Provider;
  1842.     SOCKET       ProviderSocket;
  1843.  
  1844.  
  1845.     if (PREAPINOTIFY(( DTCODE_WSPIoctl,
  1846.                        &ReturnValue,
  1847.                        gLibraryName,
  1848.                        &s,
  1849.                        &dwIoControlCode,
  1850.                        &lpvInBuffer,
  1851.                        &cbInBuffer,
  1852.                        &lpvOutBuffer,
  1853.                        &cbOutBuffer,
  1854.                        &lpcbBytesReturned,
  1855.                        &lpOverlapped,
  1856.                        &lpCompletionRoutine,
  1857.                        &lpThreadId,
  1858.                        &lpErrno)) ) {
  1859.         return(ReturnValue);
  1860.     }
  1861.  
  1862.  
  1863.     //
  1864.     // Get our DSOCKET object
  1865.     //
  1866.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  1867.         s,
  1868.         (DWORD*)&Socket,
  1869.         lpErrno);
  1870.     if (SOCKET_ERROR != ReturnValue){
  1871.         if (lpOverlapped){
  1872.             if (lpCompletionRoutine
  1873.                     || (lpOverlapped->hEvent==NULL)
  1874.                     || ResetEvent ((HANDLE)((DWORD)lpOverlapped->hEvent&0xFFFFFFFE))) {
  1875.                 PDWORKERTHREAD  Thread = GetWorkerThread ();
  1876.                 if (Thread!=NULL) {
  1877.                     // Setup the user overlapped struct
  1878.                     lpOverlapped->Internal = WSS_OPERATION_IN_PROGRESS;
  1879.                     lpOverlapped->InternalHigh = 0;
  1880.                     ReturnValue = Thread->QueueOverlappedIoctl(
  1881.                         Socket,
  1882.                         dwIoControlCode,
  1883.                         lpvInBuffer,
  1884.                         cbInBuffer,
  1885.                         lpvOutBuffer,
  1886.                         cbOutBuffer,
  1887.                         lpcbBytesReturned,
  1888.                         lpOverlapped,
  1889.                         lpCompletionRoutine,
  1890.                         lpThreadId,
  1891.                         lpErrno);
  1892.                 }
  1893.                 else {
  1894.                     ReturnValue = SOCKET_ERROR;
  1895.                     *lpErrno = WSAENOBUFS;
  1896.                 }
  1897.             }
  1898.             else {
  1899.                 ReturnValue = SOCKET_ERROR;
  1900.                 *lpErrno = WSA_INVALID_PARAMETER;
  1901.             }
  1902.         }
  1903.         else {
  1904.             Provider = Socket->GetDProvider ();
  1905.             ProviderSocket = Socket->GetProviderSocket ();
  1906.  
  1907.             ReturnValue = Provider->WSPIoctl(
  1908.                 ProviderSocket,
  1909.                 dwIoControlCode,
  1910.                 lpvInBuffer,
  1911.                 cbInBuffer,
  1912.                 lpvOutBuffer,
  1913.                 cbOutBuffer,
  1914.                 lpcbBytesReturned,
  1915.                 lpOverlapped,
  1916.                 lpCompletionRoutine,
  1917.                 lpThreadId,
  1918.                 lpErrno);
  1919.             if ((dwIoControlCode==SIO_GET_EXTENSION_FUNCTION_POINTER)
  1920.                     && (NO_ERROR==ReturnValue)) {
  1921.                 ReturnValue = Provider->InterceptExtensions (
  1922.                                     lpvInBuffer,
  1923.                                     lpvOutBuffer,
  1924.                                     lpErrno);
  1925.             }
  1926.         }
  1927.     } //if
  1928.  
  1929.     POSTAPINOTIFY(( DTCODE_WSPIoctl,
  1930.                     &ReturnValue,
  1931.                     gLibraryName,
  1932.                     &s,
  1933.                     &dwIoControlCode,
  1934.                     &lpvInBuffer,
  1935.                     &cbInBuffer,
  1936.                     &lpvOutBuffer,
  1937.                     &cbOutBuffer,
  1938.                     &lpcbBytesReturned,
  1939.                     &lpOverlapped,
  1940.                     &lpCompletionRoutine,
  1941.                     &lpThreadId,
  1942.                     &lpErrno));
  1943.  
  1944.     return(ReturnValue);
  1945. }
  1946.  
  1947.  
  1948. SOCKET
  1949. WSPAPI
  1950. WSPJoinLeaf(
  1951.     IN SOCKET s,
  1952.     IN const struct sockaddr FAR *name,
  1953.     IN INT namelen,
  1954.     IN LPWSABUF lpCallerData,
  1955.     IN LPWSABUF lpCalleeData,
  1956.     IN LPQOS lpSQOS,
  1957.     IN LPQOS lpGQOS,
  1958.     IN DWORD dwFlags,
  1959.     OUT INT FAR *lpErrno
  1960.     )
  1961. /*++
  1962. Routine Description:
  1963.  
  1964.     Join  a  leaf  node  into  a multipoint session, exchange connect data, and
  1965.     specify needed quality of service based on the supplied flow specs.
  1966.  
  1967. Arguments:
  1968.  
  1969.     s            - A descriptor identifying a multipoint socket.
  1970.  
  1971.     name         - The name of the peer to which the socket is to be joined.
  1972.  
  1973.     namelen      - The length of the name.
  1974.  
  1975.     lpCallerData - A  pointer to the user data that is to be transferred to the
  1976.                    peer during multipoint session establishment.
  1977.  
  1978.     lpCalleeData - A  pointer  to  the user data that is to be transferred back
  1979.                    from the peer during multipoint session establishment.
  1980.  
  1981.     lpSQOS       - A  pointer  to  the  flow  specs  for socket s, one for each
  1982.                    direction.
  1983.  
  1984.     lpGQOS       - A  pointer  to  the  flow  specs  for  the  socket group (if
  1985.                    applicable).
  1986.  
  1987.     dwFlags      - Flags  to  indicate  that  the socket is acting as a sender,
  1988.                    receiver, or both.
  1989.  
  1990.     lpErrno      - A pointer to the error code.
  1991.  
  1992. Return Value:
  1993.  
  1994.     If no error occurs, WSPJoinLeaf() returns a value of type SOCKET which is a
  1995.     descriptor  for the newly created multipoint socket.  Otherwise,a value of
  1996.     INVALID_SOCKET  is  returned, and  a  specific  error code is available in
  1997.     lpErrno.
  1998.  
  1999. --*/
  2000. {
  2001.     INT             ReturnValue;
  2002.     PDSOCKET     Socket, NewSocket;
  2003.     PDPROVIDER   Provider;
  2004.     SOCKET       ProviderSocket, NewProviderSocket;
  2005.     DWORD         ThisProviderCatalogEntryId;
  2006.  
  2007.  
  2008.     if (PREAPINOTIFY(( DTCODE_WSPJoinLeaf,
  2009.                        &ReturnValue,
  2010.                        gLibraryName,
  2011.                        &s,
  2012.                        &name,
  2013.                        &namelen,
  2014.                        &lpCallerData,
  2015.                        &lpCalleeData,
  2016.                        &lpSQOS,
  2017.                        &lpGQOS,
  2018.                        &dwFlags,
  2019.                        &lpErrno)) ) {
  2020.         return(ReturnValue);
  2021.     }
  2022.  
  2023.     //
  2024.     // Get our DSOCKET object
  2025.     //
  2026.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  2027.         s,
  2028.         (DWORD*)&Socket,
  2029.         lpErrno);
  2030.     if (SOCKET_ERROR != ReturnValue){
  2031.         Provider = Socket->GetDProvider();
  2032.         ProviderSocket = Socket->GetProviderSocket();
  2033.  
  2034.         NewProviderSocket = Provider->WSPJoinLeaf(
  2035.             ProviderSocket,
  2036.             name,
  2037.             namelen,
  2038.             lpCallerData,
  2039.             lpCalleeData,
  2040.             lpSQOS,
  2041.             lpGQOS,
  2042.             dwFlags,
  2043.             lpErrno);
  2044.         if (NewProviderSocket!=INVALID_SOCKET) {
  2045.             if (NewProviderSocket!=ProviderSocket) {
  2046.                 //
  2047.                 // Create a new socket object and initialize it.
  2048.                 NewSocket = new DSOCKET;
  2049.                 if (NewSocket){
  2050.                     ThisProviderCatalogEntryId = 
  2051.                         gProviderCatalog->GetLocalProvider()->GetProtocolInfo()->dwCatalogEntryId;
  2052.  
  2053.                     ReturnValue = gUpCallTable.lpWPUCreateSocketHandle(
  2054.                         ThisProviderCatalogEntryId,
  2055.                         (DWORD) NewSocket,
  2056.                         lpErrno);
  2057.                     DEBUGF( DBG_TRACE,
  2058.                             ("JoinLeaf Returning Socket %X\n", ReturnValue));
  2059.  
  2060.                     if (INVALID_SOCKET != ReturnValue){
  2061.                         NewSocket->Initialize(
  2062.                             Provider,
  2063.                             NewProviderSocket,
  2064.                             Socket->GetCatalogEntryId(),
  2065.                             ReturnValue);
  2066.  
  2067.                     } //if
  2068.                     else{
  2069.                         delete NewSocket;
  2070.                         Provider->WSPCloseSocket (NewProviderSocket, lpErrno);
  2071.                     } //else
  2072.                 }
  2073.             }
  2074.             else
  2075.                 ReturnValue = s;
  2076.         }
  2077.         else
  2078.             ReturnValue = INVALID_SOCKET;
  2079.     } //if
  2080.  
  2081.     POSTAPINOTIFY(( DTCODE_WSPJoinLeaf,
  2082.                     &ReturnValue,
  2083.                     gLibraryName,
  2084.                     &s,
  2085.                     &name,
  2086.                     &namelen,
  2087.                     &lpCallerData,
  2088.                     &lpCalleeData,
  2089.                     &lpSQOS,
  2090.                     &lpGQOS,
  2091.                     &dwFlags,
  2092.                     &lpErrno));
  2093.  
  2094.     return(ReturnValue);
  2095.  
  2096. }
  2097.  
  2098.  
  2099.  
  2100. INT
  2101. WSPAPI
  2102. WSPListen(
  2103.     IN SOCKET s,
  2104.     IN INT backlog,
  2105.     OUT INT FAR *lpErrno
  2106.     )
  2107. /*++
  2108. Routine Description:
  2109.  
  2110.     Establish a socket to listen for incoming connections.
  2111.  
  2112. Arguments:
  2113.  
  2114.     s       - A descriptor identifying a bound,
  2115. unconnected socket.
  2116.  
  2117.     backlog - The  maximum length to which the queue of pending connections may
  2118.               grow.   If  this  value  is  SOMAXCONN,
  2119. then the service provider
  2120.               should set the backlog to a maximum "reasonable" value.
  2121.  
  2122.     lpErrno - A pointer to the error code.
  2123.  
  2124. Return Value:
  2125.  
  2126.     If  no  error  occurs, WSPListen()  returns  0.   Otherwise, a  value  of
  2127.     SOCKET_ERROR  is  returned, and  a  specific  error  code  is available in
  2128.     lpErrno.
  2129.  
  2130. --*/
  2131. {
  2132.     INT ReturnValue;
  2133.     PDSOCKET     Socket;
  2134.     PDPROVIDER   Provider;
  2135.     SOCKET       ProviderSocket;
  2136.  
  2137.  
  2138.     if (PREAPINOTIFY(( DTCODE_WSPListen,
  2139.                        &ReturnValue,
  2140.                        gLibraryName,
  2141.                        &s,
  2142.                        &backlog,
  2143.                        &lpErrno)) ) {
  2144.         return(ReturnValue);
  2145.     }
  2146.  
  2147.     //
  2148.     // Get our DSOCKET object
  2149.     //
  2150.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  2151.         s,
  2152.         (DWORD*)&Socket,
  2153.         lpErrno);
  2154.     if (SOCKET_ERROR != ReturnValue){
  2155.         Provider = Socket->GetDProvider();
  2156.         ProviderSocket = Socket->GetProviderSocket();
  2157.  
  2158.         ReturnValue = Provider->WSPListen(
  2159.             ProviderSocket,
  2160.             backlog,
  2161.             lpErrno);
  2162.     } //if
  2163.  
  2164.     POSTAPINOTIFY(( DTCODE_WSPListen,
  2165.                     &ReturnValue,
  2166.                     gLibraryName,
  2167.                     &s,
  2168.                     &backlog,
  2169.                     &lpErrno));
  2170.  
  2171.     return(ReturnValue);
  2172. }
  2173.  
  2174.  
  2175.  
  2176. INT
  2177. WSPAPI
  2178. WSPRecv(
  2179.     IN SOCKET s,
  2180.     IN LPWSABUF lpBuffers,
  2181.     IN DWORD dwBufferCount,
  2182.     IN LPDWORD lpNumberOfBytesRecvd,
  2183.     IN OUT LPDWORD lpFlags,
  2184.     IN LPWSAOVERLAPPED lpOverlapped,
  2185.     IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  2186.     IN LPWSATHREADID lpThreadId,
  2187.     OUT INT FAR *lpErrno
  2188.     )
  2189. /*++
  2190. Routine Description:
  2191.  
  2192.     Receive data on a socket.
  2193.  
  2194. Arguments:
  2195.  
  2196.     s                    - A descriptor identifying a connected socket.
  2197.  
  2198.     lpBuffers            - A  pointer  to  an array of WSABUF structures.  Each
  2199.                            WSABUF  structure contains a pointer to a buffer and
  2200.                            the length of the buffer.
  2201.  
  2202.     dwBufferCount        - The  number  of  WSABUF  structures in the lpBuffers
  2203.                            array.
  2204.  
  2205.     lpNumberOfBytesRecvd - A  pointer  to  the number of bytes received by this
  2206.                            call.
  2207.  
  2208.     lpFlags              - A pointer to flags.
  2209.  
  2210.     lpOverlapped         - A pointer to a WSAOVERLAPPED structure.
  2211.  
  2212.     lpCompletionRoutine  - A  pointer to the completion routine called when the
  2213.                            receive operation has been completed.
  2214.  
  2215.     lpThreadId           - A pointer to a thread ID structure to be used by the
  2216.                            provider in a subsequent call to WPUQueueApc().
  2217.  
  2218.     lpErrno              - A pointer to the error code.
  2219.  
  2220. Return Value:
  2221.  
  2222.     If  no  error  occurs  and the receive operation has completed immediately,
  2223.     WSPRecv() returns the number of bytes received.  If the connection has been
  2224.     closed, it  returns  0.  Note that in this case the completion routine, if
  2225.     specified,  will   have  already  been  queued.   Otherwise, a  value  of
  2226.     SOCKET_ERROR  is  returned, and  a  specific  error  code  is available in
  2227.     lpErrno.   The  error  code WSA_IO_PENDING indicates that the overlapped an
  2228.     operation  has  been  successfully  initiated  and  that completion will be
  2229.     indicated  at  a  later  time.   Any  other  error  code  indicates that no
  2230.     overlapped  operations  was  initiated  and  no  completion indication will
  2231.     occur.
  2232. --*/
  2233. {
  2234.     INT ReturnValue;
  2235.     PDSOCKET         Socket;
  2236.     PDPROVIDER       Provider;
  2237.     SOCKET           ProviderSocket;
  2238.     LPWSABUF         InternalBuffers;
  2239.     DWORD            InternalBufferCount;
  2240.  
  2241.  
  2242.     if (PREAPINOTIFY(( DTCODE_WSPRecv,
  2243.                        &ReturnValue,
  2244.                        gLibraryName,
  2245.                        &s,
  2246.                        &lpBuffers,
  2247.                        &dwBufferCount,
  2248.                        &lpNumberOfBytesRecvd,
  2249.                        &lpFlags,
  2250.                        &lpOverlapped,
  2251.                        &lpCompletionRoutine,
  2252.                        &lpThreadId,
  2253.                        &lpErrno)) ) {
  2254.         return(ReturnValue);
  2255.     }
  2256.  
  2257.     //
  2258.     // Get our DSOCKET object
  2259.     //
  2260.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  2261.         s,
  2262.         (DWORD*)&Socket,
  2263.         lpErrno);
  2264.     if (SOCKET_ERROR != ReturnValue){
  2265.  
  2266.         // Get Internal buffers to send down to the lower provider.
  2267.         ReturnValue = gBufferManager->AllocBuffer(
  2268.             lpBuffers,
  2269.             dwBufferCount,
  2270.             &InternalBuffers,
  2271.             &InternalBufferCount);
  2272.  
  2273.         if (NO_ERROR == ReturnValue){
  2274.             //Is this a overlapped operation.
  2275.             if (lpOverlapped){
  2276.                 if (lpCompletionRoutine
  2277.                         || (lpOverlapped->hEvent==NULL)
  2278.                         || ResetEvent ((HANDLE)((DWORD)lpOverlapped->hEvent&0xFFFFFFFE))) {
  2279.                     PDWORKERTHREAD  Thread = GetWorkerThread ();
  2280.                     if (Thread!=NULL) {
  2281.                         // Setup the user overlapped struct
  2282.                         lpOverlapped->Internal = WSS_OPERATION_IN_PROGRESS;
  2283.                         lpOverlapped->InternalHigh = 0;
  2284.                         ReturnValue = Thread->QueueOverlappedRecv(
  2285.                             Socket,
  2286.                             lpBuffers,
  2287.                             dwBufferCount,
  2288.                             lpNumberOfBytesRecvd,
  2289.                             lpFlags,
  2290.                             lpOverlapped,
  2291.                             lpCompletionRoutine,
  2292.                             lpThreadId,
  2293.                             InternalBuffers,
  2294.                             InternalBufferCount,
  2295.                             lpErrno);
  2296.                     }
  2297.                     else {
  2298.                         ReturnValue = SOCKET_ERROR;
  2299.                         *lpErrno = WSAENOBUFS;
  2300.                     }
  2301.                 }
  2302.                 else {
  2303.                     ReturnValue = SOCKET_ERROR;
  2304.                     *lpErrno = WSA_INVALID_PARAMETER;
  2305.                 }
  2306.             } //if
  2307.             else{
  2308.                 Provider = Socket->GetDProvider();
  2309.                 ProviderSocket = Socket->GetProviderSocket();
  2310.  
  2311.                 SetBlockingProvider (Provider);
  2312.                 ReturnValue = Provider->WSPRecv(
  2313.                     ProviderSocket,
  2314.                     InternalBuffers,
  2315.                     InternalBufferCount,
  2316.                     lpNumberOfBytesRecvd,
  2317.                     lpFlags,
  2318.                     lpOverlapped,
  2319.                     lpCompletionRoutine,
  2320.                     lpThreadId,
  2321.                     lpErrno);
  2322.                 SetBlockingProvider (NULL);
  2323.                 if (ReturnValue==NO_ERROR) {
  2324.                     gBufferManager->CopyBuffer (InternalBuffers,
  2325.                                 InternalBufferCount,
  2326.                                 0,
  2327.                                 *lpNumberOfBytesRecvd,
  2328.                                 lpBuffers,
  2329.                                 dwBufferCount,
  2330.                                 0);
  2331.                 }
  2332.                 gBufferManager->FreeBuffer (InternalBuffers, InternalBufferCount);
  2333.             } //else
  2334.         } //if
  2335.     } //if
  2336.  
  2337.     POSTAPINOTIFY(( DTCODE_WSPRecv,
  2338.                     &ReturnValue,
  2339.                     gLibraryName,
  2340.                     &s,
  2341.                     &lpBuffers,
  2342.                     &dwBufferCount,
  2343.                     &lpNumberOfBytesRecvd,
  2344.                     &lpFlags,
  2345.                     &lpOverlapped,
  2346.                     &lpCompletionRoutine,
  2347.                     &lpThreadId,
  2348.                     &lpErrno));
  2349.  
  2350.     return(ReturnValue);
  2351. }
  2352.  
  2353.  
  2354.  
  2355.  INT
  2356. WSPAPI
  2357. WSPRecvDisconnect(
  2358.     IN SOCKET s,
  2359.     IN LPWSABUF lpInboundDisconnectData,
  2360.     OUT INT FAR *lpErrno
  2361.     )
  2362. /*++
  2363. Routine Description:
  2364.  
  2365.     Terminate  reception  on  a socket, and retrieve the disconnect data if the
  2366.     socket is connection-oriented.
  2367.  
  2368. Arguments:
  2369.  
  2370.     s                       - A descriptor identifying a socket.
  2371.  
  2372.     lpInboundDisconnectData - A  pointer to a buffer into which disconnect data
  2373.                               is to be copied.
  2374.  
  2375.     lpErrno                 - A pointer to the error code.
  2376.  
  2377. Return Value:
  2378.  
  2379.     If  no error occurs, WSPRecvDisconnect() returns NO_ERROR.  Otherwise,
  2380.     a value of SOCKET_ERROR is returned, and a specific error code is available
  2381.     in lpErrno.
  2382.  
  2383. --*/
  2384. {
  2385.     INT ReturnValue;
  2386.     PDSOCKET     Socket;
  2387.     PDPROVIDER   Provider;
  2388.     SOCKET       ProviderSocket;
  2389.  
  2390.  
  2391.     if (PREAPINOTIFY(( DTCODE_WSPRecvDisconnect,
  2392.                        &ReturnValue,
  2393.                        gLibraryName,
  2394.                        &s,
  2395.                        &lpInboundDisconnectData,
  2396.                        &lpErrno)) ) {
  2397.         return(ReturnValue);
  2398.     }
  2399.  
  2400.     //
  2401.     // Get our DSOCKET object
  2402.     //
  2403.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  2404.         s,
  2405.         (DWORD*)&Socket,
  2406.         lpErrno);
  2407.  
  2408.     if (SOCKET_ERROR != ReturnValue){
  2409.         Provider = Socket->GetDProvider();
  2410.         ProviderSocket = Socket->GetProviderSocket();
  2411.  
  2412.         ReturnValue = Provider->WSPRecvDisconnect(
  2413.             ProviderSocket,
  2414.             lpInboundDisconnectData,
  2415.             lpErrno);
  2416.     } //if
  2417.  
  2418.     POSTAPINOTIFY(( DTCODE_WSPRecvDisconnect,
  2419.                     &ReturnValue,
  2420.                     gLibraryName,
  2421.                     &s,
  2422.                     &lpInboundDisconnectData,
  2423.                     &lpErrno));
  2424.  
  2425.     return(ReturnValue);
  2426.  
  2427. }
  2428.  
  2429.  
  2430.  
  2431. INT
  2432. WSPAPI
  2433. WSPRecvFrom(
  2434.     IN  SOCKET s,
  2435.     IN  LPWSABUF lpBuffers,
  2436.     IN  DWORD dwBufferCount,
  2437.     IN  LPDWORD lpNumberOfBytesRecvd,
  2438.     IN  OUT LPDWORD lpFlags,
  2439.     OUT struct sockaddr FAR *  lpFrom,
  2440.     IN  LPINT lpFromlen,
  2441.     IN  LPWSAOVERLAPPED lpOverlapped,
  2442.     IN  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  2443.     IN LPWSATHREADID lpThreadId,
  2444.     OUT INT FAR *lpErrno
  2445.     )
  2446. /*++
  2447. Routine Description:
  2448.  
  2449.     Receive a datagram and store the source address.
  2450.  
  2451. Arguments:
  2452.  
  2453.     s                    - A descriptor identifying a socket.
  2454.  
  2455.     lpBuffers            - A  pointer  to  an array of WSABUF structures.  Each
  2456.                            WSABUF  structure contains a pointer to a buffer and
  2457.                            the length of the buffer.
  2458.  
  2459.     dwBufferCount        - The  number  of  WSABUF  structures in the lpBuffers
  2460.                            array.
  2461.  
  2462.     lpNumberOfBytesRecvd - A  pointer  to  the number of bytes received by this
  2463.                            call.
  2464.  
  2465.     lpFlags              - A pointer to flags.
  2466.  
  2467.     lpFrom               - An  optional pointer to a buffer which will hold the
  2468.                            source address upon the completion of the overlapped
  2469.                            operation.
  2470.  
  2471.     lpFromlen            - A  pointer  to the size of the from buffer, required
  2472.                            only if lpFrom is specified.
  2473.  
  2474.     lpOverlapped         - A pointer to a WSAOVERLAPPED structure.
  2475.  
  2476.     CompletionRoutine    - A  pointer to the completion routine called when the
  2477.                            receive operation has been completed.
  2478.  
  2479.     lpThreadId           - A pointer to a thread ID structure to be used by the
  2480.                            provider in a subsequent call to WPUQueueApc().
  2481.  
  2482.     lpErrno              - A pointer to the error code.
  2483.  
  2484. Return Value:
  2485.  
  2486.     If  no  error  occurs  and the receive operation has completed immediately,
  2487.     WSPRecvFrom()  returns the number of bytes received.  If the connection has
  2488.     been  closed, it returns 0.  Note that in this case the completion routine,
  2489.     if  specified  will  have  already  been  queued.   Otherwise,  a  value of
  2490.     SOCKET_ERROR  is  returned, and  a  specific  error  code  is available in
  2491.     lpErrno.   The  error  code  WSA_IO_PENDING  indicates  that the overlapped
  2492.     operation  has  been  successfully  initiated  and  that completion will be
  2493.     indicated  at  a  later  time.   Any  other  error  code  indicates that no
  2494.     overlapped  operations  was  initiated  and  no  completion indication will
  2495.     occur.
  2496.  
  2497. --*/
  2498. {
  2499.     INT              ReturnValue;
  2500.     PDSOCKET         Socket;
  2501.     PDPROVIDER       Provider;
  2502.     SOCKET           ProviderSocket;
  2503.     LPWSABUF         InternalBuffers;
  2504.     DWORD            InternalBufferCount;
  2505.  
  2506.  
  2507.     if (PREAPINOTIFY(( DTCODE_WSPRecvFrom,
  2508.                        &ReturnValue,
  2509.                        gLibraryName,
  2510.                        &s,
  2511.                        &lpBuffers,
  2512.                        &dwBufferCount,
  2513.                        &lpNumberOfBytesRecvd,
  2514.                        &lpFlags,
  2515.                        &lpFrom,
  2516.                        &lpFromlen,
  2517.                        &lpOverlapped,
  2518.                        &lpCompletionRoutine,
  2519.                        &lpThreadId,
  2520.                        &lpErrno)) ) {
  2521.         return(ReturnValue);
  2522.     }
  2523.  
  2524.     //
  2525.     // Get our DSOCKET object
  2526.     //
  2527.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  2528.         s,
  2529.         (DWORD*)&Socket,
  2530.         lpErrno);
  2531.     if (SOCKET_ERROR != ReturnValue){
  2532.  
  2533.         // Get Internal buffers to send down to the lower provider.
  2534.         ReturnValue = gBufferManager->AllocBuffer(
  2535.             lpBuffers,
  2536.             dwBufferCount,
  2537.             &InternalBuffers,
  2538.             &InternalBufferCount);
  2539.  
  2540.         if (NO_ERROR == ReturnValue){
  2541.             //Is this a overlapped operation.
  2542.             if (lpOverlapped){
  2543.                 if (lpCompletionRoutine
  2544.                         || (lpOverlapped->hEvent==NULL)
  2545.                         || ResetEvent ((HANDLE)((DWORD)lpOverlapped->hEvent&0xFFFFFFFE))) {
  2546.                     PDWORKERTHREAD  Thread = GetWorkerThread ();
  2547.                     if (Thread!=NULL) {
  2548.                         // Setup the user overlapped struct
  2549.                         lpOverlapped->Internal = WSS_OPERATION_IN_PROGRESS;
  2550.                         lpOverlapped->InternalHigh = 0;
  2551.                         ReturnValue = Thread->QueueOverlappedRecvFrom(
  2552.                             Socket,
  2553.                             InternalBuffers,
  2554.                             InternalBufferCount,
  2555.                             lpNumberOfBytesRecvd,
  2556.                             lpFlags,
  2557.                             lpFrom,
  2558.                             lpFromlen,
  2559.                             lpOverlapped,
  2560.                             lpCompletionRoutine,
  2561.                             lpThreadId,
  2562.                             InternalBuffers,
  2563.                             InternalBufferCount,
  2564.                             lpErrno);
  2565.                     }
  2566.                     else {
  2567.                         ReturnValue = SOCKET_ERROR;
  2568.                         *lpErrno = WSAENOBUFS;
  2569.                     }
  2570.                 }
  2571.                 else {
  2572.                     ReturnValue = SOCKET_ERROR;
  2573.                     *lpErrno = WSA_INVALID_PARAMETER;
  2574.                 }
  2575.             } //if
  2576.             else{
  2577.                 Provider = Socket->GetDProvider();
  2578.                 ProviderSocket = Socket->GetProviderSocket();
  2579.  
  2580.                 SetBlockingProvider (Provider);
  2581.                 ReturnValue = Provider->WSPRecvFrom(
  2582.                     ProviderSocket,
  2583.                     lpBuffers,
  2584.                     dwBufferCount,
  2585.                     lpNumberOfBytesRecvd,
  2586.                     lpFlags,
  2587.                     lpFrom,
  2588.                     lpFromlen,
  2589.                     lpOverlapped,
  2590.                     lpCompletionRoutine,
  2591.                     lpThreadId,
  2592.                     lpErrno);
  2593.                 SetBlockingProvider (NULL);
  2594.                 if (ReturnValue==NO_ERROR) {
  2595.                     gBufferManager->CopyBuffer (InternalBuffers,
  2596.                                 InternalBufferCount,
  2597.                                 0,
  2598.                                 *lpNumberOfBytesRecvd,
  2599.                                 lpBuffers,
  2600.                                 dwBufferCount,
  2601.                                 0);
  2602.                 }
  2603.                 gBufferManager->FreeBuffer (InternalBuffers, InternalBufferCount);
  2604.             } //else
  2605.         } //if
  2606.     } //if
  2607.  
  2608.     POSTAPINOTIFY(( DTCODE_WSPRecvFrom,
  2609.                     &ReturnValue,
  2610.                     gLibraryName,
  2611.                     &s,
  2612.                     &lpBuffers,
  2613.                     &dwBufferCount,
  2614.                     &lpNumberOfBytesRecvd,
  2615.                     &lpFlags,
  2616.                     &lpFrom,
  2617.                     &lpFromlen,
  2618.                     &lpOverlapped,
  2619.                     &lpCompletionRoutine,
  2620.                     &lpThreadId,
  2621.                     &lpErrno));
  2622.  
  2623.     return(ReturnValue);
  2624. }
  2625.  
  2626. typedef struct association
  2627. {
  2628.     SOCKET  ProviderSocket;
  2629.     SOCKET  UserSocket;
  2630. } SOCKETASSOCIATION, *PSOCKETASSOCIATION;
  2631.  
  2632. typedef struct
  2633. {
  2634.     UINT                AssociationCount;
  2635.     PSOCKETASSOCIATION  Associations;
  2636. } SOCKETMAP, *PSOCKETMAP;
  2637.  
  2638.  
  2639.  
  2640. INT
  2641. TransferUserFdSetToProviderFdSet(
  2642.     IN  fd_set * UserSet,
  2643.     OUT fd_set * ProviderSet,
  2644.     OUT PSOCKETMAP SocketMap,
  2645.     OUT LPINT    Errno)
  2646. {
  2647.     INT ReturnCode;
  2648.     UINT Index;
  2649.     PDSOCKET Socket;
  2650.  
  2651.     ReturnCode= NO_ERROR;
  2652.     SocketMap->AssociationCount = 0;
  2653.     SocketMap->Associations     = NULL;
  2654.     ProviderSet->fd_count       = 0;
  2655.  
  2656.     if (UserSet && (UserSet->fd_count > 0)){
  2657.         if (UserSet->fd_count > FD_SETSIZE){
  2658.             *Errno = WSAENOBUFS;
  2659.             return(SOCKET_ERROR);
  2660.         } //if
  2661.         SocketMap->Associations = (PSOCKETASSOCIATION)new BYTE[
  2662.             (sizeof(SOCKETASSOCIATION) * UserSet->fd_count)];
  2663.         if (SocketMap->Associations){
  2664.  
  2665.             for (Index=0;Index < UserSet->fd_count  ;Index++ ){
  2666.  
  2667.                 ReturnCode = gUpCallTable.lpWPUQuerySocketHandleContext(
  2668.                     UserSet->fd_array[Index],
  2669.                     (DWORD*)&Socket,
  2670.                     Errno);
  2671.                 if (NO_ERROR != ReturnCode){
  2672.                     delete(SocketMap->Associations);
  2673.                     SocketMap->Associations = NULL;
  2674.                     *Errno = WSAEINVAL;
  2675.                     break;
  2676.                 } //if
  2677.  
  2678.                 SocketMap->Associations[Index].ProviderSocket =
  2679.                     Socket->GetProviderSocket();
  2680.                 SocketMap->Associations[Index].UserSocket =
  2681.                     UserSet->fd_array[Index];
  2682.                 ProviderSet->fd_array[Index] =
  2683.                     SocketMap->Associations[Index].ProviderSocket;
  2684.  
  2685.                 ProviderSet->fd_count++;
  2686.                 SocketMap->AssociationCount++;
  2687.             } //for
  2688.         } //if
  2689.         else{
  2690.              ReturnCode =SOCKET_ERROR;
  2691.             *Errno = WSAENOBUFS;
  2692.         } //else
  2693.     } //if
  2694.     return(ReturnCode);
  2695. }
  2696.  
  2697. INT
  2698. TransferProviderFdSetToUserFdSet(
  2699.     IN  fd_set *   UserSet,
  2700.     OUT fd_set *   ProviderSet,
  2701.     IN  PSOCKETMAP SocketMap,
  2702.     OUT LPINT      Errno)
  2703. {
  2704.     INT ReturnCode;
  2705.     UINT ProviderIndex;
  2706.     UINT AssociationIndex;
  2707.  
  2708.     ReturnCode= NO_ERROR;
  2709.  
  2710.     if (UserSet) {
  2711.         UserSet->fd_count = 0;
  2712.         for (ProviderIndex = 0;
  2713.              ProviderIndex < ProviderSet->fd_count;
  2714.              ProviderIndex++){
  2715.  
  2716.             for (AssociationIndex =0;
  2717.                  AssociationIndex < SocketMap->AssociationCount;
  2718.                  AssociationIndex++){
  2719.  
  2720.                 if (ProviderSet->fd_array[ProviderIndex] ==
  2721.                     SocketMap->Associations[AssociationIndex].ProviderSocket){
  2722.  
  2723.                     UserSet->fd_array[ProviderIndex] =
  2724.                         SocketMap->Associations[AssociationIndex].UserSocket;
  2725.                     UserSet->fd_count++;
  2726.                 } //if
  2727.             } //for
  2728.         } //for
  2729.         delete SocketMap->Associations;
  2730.     } //if
  2731.  
  2732.     return(ReturnCode);
  2733.  
  2734. }
  2735.  
  2736. INT
  2737. WSPAPI
  2738. WSPSelect(
  2739.     IN INT nfds,
  2740.     IN OUT fd_set FAR *readfds,
  2741.     IN OUT fd_set FAR *writefds,
  2742.     IN OUT fd_set FAR *exceptfds,
  2743.     IN const struct timeval FAR *timeout,
  2744.     OUT INT FAR *lpErrno
  2745.     )
  2746. /*++
  2747. Routine Description:
  2748.  
  2749.     Determine the status of one or more sockets.
  2750.  
  2751. Arguments:
  2752.  
  2753.     nfds      - This  argument  is  ignored  and  included only for the sake of
  2754.                 compatibility.
  2755.  
  2756.     readfds   - An  optional  pointer  to  a  set  of sockets to be checked for
  2757.                 readability.
  2758.  
  2759.     writefds  - An  optional  pointer  to  a  set  of sockets to be checked for
  2760.                 writability
  2761.  
  2762.     exceptfds - An  optional  pointer  to  a  set  of sockets to be checked for
  2763.                 errors.
  2764.  
  2765.     timeout   - The  maximum  time  for  WSPSelect()  to  wait, or  NULL for a
  2766.                 blocking operation.
  2767.  
  2768.     lpErrno   - A pointer to the error code.
  2769.  
  2770. Return Value:
  2771.  
  2772.     WSPSelect()  returns  the  total  number of descriptors which are ready and
  2773.     contained  in  the  fd_set  structures, 0  if  the  time limit expired, or
  2774.     SOCKET_ERROR  if an error occurred.  If the return value is SOCKET_ERROR, a
  2775.     specific error code is available in lpErrno.
  2776.  
  2777. --*/
  2778. {
  2779.     INT ReturnValue;
  2780.     PDPROVIDER   Provider;
  2781.     SOCKET       SocketHandle;
  2782.     BOOL         FoundSocket=FALSE;
  2783.     PDSOCKET     Socket;
  2784.     fd_set       InternalReadfds;
  2785.     fd_set       InternalWritefds;
  2786.     fd_set       InternalExceptfds;
  2787.     SOCKETMAP    ReadMap;
  2788.     SOCKETMAP    WriteMap;
  2789.     SOCKETMAP    ExceptMap;
  2790.  
  2791.     if (PREAPINOTIFY(( DTCODE_WSPSelect,
  2792.                        &ReturnValue,
  2793.                        gLibraryName,
  2794.                        &nfds,
  2795.                        &readfds,
  2796.                        &writefds,
  2797.                        &exceptfds,
  2798.                        &timeout,
  2799.                        &lpErrno)) ) {
  2800.         return(ReturnValue);
  2801.     }
  2802.  
  2803.     // Look for a socket in the three fd_sets handed in. The first
  2804.     // socket found will be used to select the service provider to
  2805.     // service this call
  2806.     if (readfds && readfds->fd_count){
  2807.  
  2808.         SocketHandle = readfds->fd_array[0];
  2809.         FoundSocket = TRUE;
  2810.     } //if
  2811.  
  2812.     if (!FoundSocket && writefds && writefds->fd_count ){
  2813.  
  2814.         SocketHandle = writefds->fd_array[0];
  2815.         FoundSocket = TRUE;
  2816.     } //if
  2817.  
  2818.     if (!FoundSocket && exceptfds && exceptfds->fd_count ){
  2819.  
  2820.         SocketHandle = exceptfds->fd_array[0];
  2821.         FoundSocket = TRUE;
  2822.     } //if
  2823.     if (FoundSocket){
  2824.         //
  2825.         // Get our DSOCKET object
  2826.         //
  2827.         ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  2828.             SocketHandle,
  2829.             (DWORD*)&Socket,
  2830.             lpErrno);
  2831.         if (SOCKET_ERROR != ReturnValue){
  2832.             Provider = Socket->GetDProvider();
  2833.  
  2834.             TransferUserFdSetToProviderFdSet(
  2835.                 readfds,
  2836.                 &InternalReadfds,
  2837.                 &ReadMap,
  2838.                 lpErrno);
  2839.             TransferUserFdSetToProviderFdSet(
  2840.                 writefds,
  2841.                 &InternalWritefds,
  2842.                 &WriteMap,
  2843.                 lpErrno);
  2844.             TransferUserFdSetToProviderFdSet(
  2845.                 exceptfds,
  2846.                 &InternalExceptfds,
  2847.                 &ExceptMap,
  2848.                 lpErrno);
  2849.             if (NO_ERROR == *lpErrno){
  2850.                 SetBlockingProvider (Provider);
  2851.                 ReturnValue = Provider->WSPSelect(
  2852.                     nfds,
  2853.                     &InternalReadfds,
  2854.                     &InternalWritefds,
  2855.                     &InternalExceptfds,
  2856.                     timeout,
  2857.                     lpErrno);
  2858.                 SetBlockingProvider (NULL);
  2859.                 TransferProviderFdSetToUserFdSet(
  2860.                     readfds,
  2861.                     &InternalReadfds,
  2862.                     &ReadMap,
  2863.                     lpErrno);
  2864.                 TransferProviderFdSetToUserFdSet(
  2865.                     writefds,
  2866.                     &InternalWritefds,
  2867.                     &WriteMap,
  2868.                     lpErrno);
  2869.                 TransferProviderFdSetToUserFdSet(
  2870.                     exceptfds,
  2871.                     &InternalExceptfds,
  2872.                     &ExceptMap,
  2873.                     lpErrno);
  2874.                 DEBUGF( DBG_TRACE,
  2875.                         ("Select Returns %X\n",ReturnValue));
  2876.  
  2877.             } //if
  2878.             else{
  2879.                 DEBUGF( DBG_TRACE,
  2880.                         ("**Select failed**\n"));
  2881.  
  2882.                 ReturnValue = SOCKET_ERROR;
  2883.             } //else
  2884.         }
  2885.     } //if
  2886.     else{
  2887.         ReturnValue = SOCKET_ERROR;
  2888.         *lpErrno    = WSAEINVAL;
  2889.     } //else/if
  2890.  
  2891.     POSTAPINOTIFY(( DTCODE_WSPSelect,
  2892.                     &ReturnValue,
  2893.                     gLibraryName,
  2894.                     &nfds,
  2895.                     &readfds,
  2896.                     &writefds,
  2897.                     &exceptfds,
  2898.                     &timeout,
  2899.                     &lpErrno));
  2900.  
  2901.     return(ReturnValue);
  2902. }
  2903.  
  2904.  
  2905.  
  2906.  
  2907.  INT
  2908. WSPAPI
  2909. WSPSend(
  2910.     IN SOCKET s,
  2911.     IN LPWSABUF lpBuffers,
  2912.     IN DWORD dwBufferCount,
  2913.     IN LPDWORD lpNumberOfBytesSent,
  2914.     IN DWORD dwFlags,
  2915.     IN LPWSAOVERLAPPED lpOverlapped,
  2916.     IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  2917.     IN LPWSATHREADID lpThreadId,
  2918.     OUT INT FAR *lpErrno
  2919.     )
  2920. /*++
  2921. Routine Description:
  2922.  
  2923.     Send data on a connected socket.
  2924.  
  2925. Arguments:
  2926.  
  2927.     s                   - A descriptor identifying a connected socket.
  2928.  
  2929.     lpBuffers           - A  pointer  to  an  array of WSABUF structures.  Each
  2930.                           WSABUF  structure  contains a pointer to a buffer and
  2931.                           the length of the buffer.
  2932.  
  2933.     dwBufferCount       - The  number  of  WSABUF  structures  in the lpBuffers
  2934.                           array.
  2935.  
  2936.     lpNumberOfBytesSent - A pointer to the number of bytes sent by this call.
  2937.  
  2938.     dwFlags             - Flags.
  2939.  
  2940.     lpOverlapped        - A pointer to a WSAOVERLAPPED structure.
  2941.  
  2942.     lpCompletionRoutine - A  pointer  to the completion routine called when the
  2943.                           send operation has been completed.
  2944.  
  2945.     lpThreadId          - A  pointer to a thread ID structure to be used by the
  2946.                           provider in a subsequent call to WPUQueueApc().
  2947.  
  2948.     lpErrno             - A pointer to the error code.
  2949.  
  2950. Return Value:
  2951.  
  2952.     If  no  error  occurs  and  the  send  operation has completed immediately,
  2953.     WSPSend() returns the number of bytes received.  If the connection has been
  2954.     closed,  it  returns  0.  Note that in this case the completion routine, if
  2955.     specified, will   have  already  been  queued.   Otherwise, a  value  of
  2956.     SOCKET_ERROR  is  returned, and  a  specific  error  code  is available in
  2957.     lpErrno.   The  error  code  WSA_IO_PENDING  indicates  that the overlapped
  2958.     operation  has  been  successfully  initiated  and  that completion will be
  2959.     indicated  at  a  later  time.   Any  other  error  code  indicates that no
  2960.     overlapped operation was initiated and no completion indication will occur.
  2961.  
  2962. --*/
  2963. {
  2964.     INT              ReturnValue;
  2965.     PDSOCKET         Socket;
  2966.     PDPROVIDER       Provider;
  2967.     SOCKET           ProviderSocket;
  2968.     LPWSABUF         InternalBuffers;
  2969.     DWORD            InternalBufferCount;
  2970.  
  2971.     if (PREAPINOTIFY(( DTCODE_WSPSend,
  2972.                        &ReturnValue,
  2973.                        gLibraryName,
  2974.                        &s,
  2975.                        &lpBuffers,
  2976.                        &dwBufferCount,
  2977.                        &lpNumberOfBytesSent,
  2978.                        &dwFlags,
  2979.                        &lpOverlapped,
  2980.                        &lpCompletionRoutine,
  2981.                        &lpThreadId,
  2982.                        &lpErrno)) ) {
  2983.         return(ReturnValue);
  2984.     }
  2985.  
  2986.     //
  2987.     // Get our DSOCKET object
  2988.     //
  2989.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  2990.         s,
  2991.         (DWORD*)&Socket,
  2992.         lpErrno);
  2993.     if (SOCKET_ERROR != ReturnValue){
  2994.  
  2995.         // Get Internal buffers to send down to the lower provider.
  2996.         ReturnValue = gBufferManager->AllocBuffer(
  2997.             lpBuffers,
  2998.             dwBufferCount,
  2999.             &InternalBuffers,
  3000.             &InternalBufferCount);
  3001.  
  3002.         if (NO_ERROR == ReturnValue){
  3003.             // Copy the user buffers
  3004.             ReturnValue = gBufferManager->CopyBuffer(
  3005.                 lpBuffers,
  3006.                 dwBufferCount,
  3007.                 0,
  3008.                 0xFFFFFFFF,        // Max bytes to copy
  3009.                 InternalBuffers,
  3010.                 InternalBufferCount,
  3011.                 0);
  3012.         } //if
  3013.  
  3014.         if (NO_ERROR == ReturnValue){
  3015.             //Is this a overlapped operation.
  3016.             if (lpOverlapped){
  3017.                 if (lpCompletionRoutine
  3018.                         || (lpOverlapped->hEvent==NULL)
  3019.                         || ResetEvent ((HANDLE)((DWORD)lpOverlapped->hEvent&0xFFFFFFFE))) {
  3020.                     PDWORKERTHREAD  Thread = GetWorkerThread ();
  3021.                     if (Thread!=NULL) {
  3022.                         // Setup the user overlapped struct
  3023.                         lpOverlapped->Internal = WSS_OPERATION_IN_PROGRESS;
  3024.                         lpOverlapped->InternalHigh = 0;
  3025.                         ReturnValue = Thread->QueueOverlappedSend(
  3026.                                 Socket,
  3027.                                 InternalBuffers,
  3028.                                 InternalBufferCount,
  3029.                                 lpNumberOfBytesSent,
  3030.                                 dwFlags,
  3031.                                 lpOverlapped,
  3032.                                 lpCompletionRoutine,
  3033.                                 lpThreadId,
  3034.                                 lpErrno);
  3035.                     }
  3036.                     else {
  3037.                         ReturnValue = SOCKET_ERROR;
  3038.                         *lpErrno = WSAENOBUFS;
  3039.                     }
  3040.                 }
  3041.                 else {
  3042.                     ReturnValue = SOCKET_ERROR;
  3043.                     *lpErrno = WSA_INVALID_PARAMETER;
  3044.                 }
  3045.  
  3046.             } //if
  3047.             else{
  3048.                 Provider = Socket->GetDProvider();
  3049.                 ProviderSocket = Socket->GetProviderSocket();
  3050.  
  3051.                 SetBlockingProvider (Provider);
  3052.                 ReturnValue = Provider->WSPSend(
  3053.                     ProviderSocket,
  3054.                     InternalBuffers,
  3055.                     InternalBufferCount,
  3056.                     lpNumberOfBytesSent,
  3057.                     dwFlags,
  3058.                     lpOverlapped,
  3059.                     lpCompletionRoutine,
  3060.                     lpThreadId,
  3061.                     lpErrno);
  3062.                 SetBlockingProvider (NULL);
  3063.                 gBufferManager->FreeBuffer (InternalBuffers, InternalBufferCount);
  3064.             } //else
  3065.         } //if
  3066.     } //if
  3067.     POSTAPINOTIFY(( DTCODE_WSPSend,
  3068.                     &ReturnValue,
  3069.                     gLibraryName,
  3070.                     &s,
  3071.                     &lpBuffers,
  3072.                     &dwBufferCount,
  3073.                     &lpNumberOfBytesSent,
  3074.                     &dwFlags,
  3075.                     &lpOverlapped,
  3076.                     &lpCompletionRoutine,
  3077.                     &lpThreadId,
  3078.                     &lpErrno));
  3079.  
  3080.     return(ReturnValue);
  3081. }
  3082.  
  3083.  
  3084.  
  3085.  INT
  3086. WSPAPI
  3087. WSPSendDisconnect(
  3088.     IN SOCKET s,
  3089.     IN LPWSABUF lpOutboundDisconnectData,
  3090.     OUT INT FAR *lpErrno
  3091.     )
  3092. /*++
  3093. Routine Description:
  3094.  
  3095.     Initiate  termination  of the connection for the socket and send disconnect
  3096.     data.
  3097.  
  3098. Arguments:
  3099.  
  3100.     s                        - A descriptor identifying a socket.
  3101.  
  3102.     lpOutboundDisconnectData - A pointer to the outgoing disconnect data.
  3103.  
  3104.     lpErrno                  - A pointer to the error code.
  3105.  
  3106. Return Value:
  3107.  
  3108.     If  no  error occurs, WSPSendDisconnect() returns 0.  Otherwise, a value of
  3109.     SOCKET_ERROR  is  returned, and  a  specific  error  code  is available in
  3110.     lpErrno.
  3111.  
  3112. --*/
  3113. {
  3114.     INT ReturnValue;
  3115.     PDSOCKET     Socket;
  3116.     PDPROVIDER   Provider;
  3117.     SOCKET       ProviderSocket;
  3118.  
  3119.  
  3120.     if (PREAPINOTIFY(( DTCODE_WSPSendDisconnect,
  3121.                        &ReturnValue,
  3122.                        gLibraryName,
  3123.                        &s,
  3124.                        &lpOutboundDisconnectData,
  3125.                        &lpErrno)) ) {
  3126.         return(ReturnValue);
  3127.     }
  3128.  
  3129.     //
  3130.     // Get our DSOCKET object
  3131.     //
  3132.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  3133.         s,
  3134.         (DWORD*)&Socket,
  3135.         lpErrno);
  3136.     if (SOCKET_ERROR != ReturnValue){
  3137.         Provider = Socket->GetDProvider();
  3138.         ProviderSocket = Socket->GetProviderSocket();
  3139.  
  3140.         ReturnValue = Provider->WSPSendDisconnect(
  3141.             ProviderSocket,
  3142.             lpOutboundDisconnectData,
  3143.             lpErrno);
  3144.     } //if
  3145.  
  3146.     POSTAPINOTIFY(( DTCODE_WSPSendDisconnect,
  3147.                     &ReturnValue,
  3148.                     gLibraryName,
  3149.                     &s,
  3150.                     &lpOutboundDisconnectData,
  3151.                     &lpErrno));
  3152.  
  3153.     return(ReturnValue);
  3154.  
  3155. }
  3156.  
  3157.  
  3158.  
  3159. INT
  3160. WSPAPI
  3161. WSPSendTo(
  3162.     IN SOCKET s,
  3163.     IN LPWSABUF lpBuffers,
  3164.     IN DWORD dwBufferCount,
  3165.     IN LPDWORD lpNumberOfBytesSent,
  3166.     IN DWORD dwFlags,
  3167.     IN const struct sockaddr FAR *  lpTo,
  3168.     IN INT iTolen,
  3169.     IN LPWSAOVERLAPPED lpOverlapped,
  3170.     IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  3171.     IN LPWSATHREADID lpThreadId,
  3172.     OUT INT FAR *lpErrno
  3173.     )
  3174. /*++
  3175. Routine Description:
  3176.  
  3177.     Send data to a specific destination using overlapped I/O.
  3178.  
  3179. Arguments:
  3180.  
  3181.     s                   - A descriptor identifying a socket.
  3182.  
  3183.     lpBuffers           - A  pointer  to  an  array of WSABUF structures.  Each
  3184.                           WSABUF  structure  contains a pointer to a buffer and
  3185.                           the length of the buffer.
  3186.  
  3187.     dwBufferCount       - The  number  of  WSABUF  structures  in the lpBuffers
  3188.                           array.
  3189.  
  3190.     lpNumberOfBytesSent - A pointer to the number of bytes sent by this call.
  3191.  
  3192.     dwFlags             - Flags.
  3193.  
  3194.     lpTo                - An  optional  pointer  to  the  address of the target
  3195.                           socket.
  3196.  
  3197.     iTolen              - The size of the address in lpTo.
  3198.  
  3199.     lpOverlapped        - A pointer to a WSAOVERLAPPED structure.
  3200.  
  3201.     lpCompletionRoutine - A  pointer  to the completion routine called when the
  3202.                           send operation has been completed.
  3203.  
  3204.     lpThreadId          - A  pointer to a thread ID structure to be used by the
  3205.                           provider in a subsequent call to WPUQueueApc().
  3206.  
  3207.     lpErrno             - A pointer to the error code.
  3208.  
  3209. Return Value:
  3210.  
  3211.     If  no  error  occurs  and the receive operation has completed immediately,
  3212.     WSPSendTo()  returns  the  number of bytes received.  If the connection has
  3213.     been  closed,it returns 0.  Note that in this case the completion routine,
  3214.     if  specified, will  have  already  been  queued.   Otherwise, a value of
  3215.     SOCKET_ERROR  is  returned, and  a  specific  error  code  is available in
  3216.     lpErrno.   The  error  code  WSA_IO_PENDING  indicates  that the overlapped
  3217.     operation  has  been  successfully  initiated  and  that completion will be
  3218.     indicated  at  a  later  time.   Any  other  error  code  indicates that no
  3219.     overlapped operation was initiated and no completion indication will occur.
  3220.  
  3221. --*/
  3222.  
  3223.  
  3224. {
  3225.     INT             ReturnValue;
  3226.     PDSOCKET     Socket;
  3227.     PDPROVIDER   Provider;
  3228.     SOCKET       ProviderSocket;
  3229.     LPWSABUF     InternalBuffers;
  3230.     DWORD        InternalBufferCount;
  3231.  
  3232.  
  3233.     if (PREAPINOTIFY(( DTCODE_WSPSendTo,
  3234.                        &ReturnValue,
  3235.                        gLibraryName,
  3236.                        &s,
  3237.                        &lpBuffers,
  3238.                        &lpNumberOfBytesSent,
  3239.                        &dwFlags,
  3240.                        &lpTo,
  3241.                        &iTolen,
  3242.                        &lpOverlapped,
  3243.                        &lpCompletionRoutine,
  3244.                        &lpThreadId,
  3245.                        &lpErrno)) ) {
  3246.         return(ReturnValue);
  3247.     }
  3248.  
  3249.     //
  3250.     // Get our DSOCKET object
  3251.     //
  3252.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  3253.         s,
  3254.         (DWORD*)&Socket,
  3255.         lpErrno);
  3256.     if (SOCKET_ERROR != ReturnValue){
  3257.         // Get Internal buffers to send down to the lower provider.
  3258.         ReturnValue = gBufferManager->AllocBuffer(
  3259.             lpBuffers,
  3260.             dwBufferCount,
  3261.             &InternalBuffers,
  3262.             &InternalBufferCount);
  3263.  
  3264.         if (NO_ERROR == ReturnValue){
  3265.             // Copy the user buffers
  3266.             ReturnValue = gBufferManager->CopyBuffer(
  3267.                 lpBuffers,
  3268.                 dwBufferCount,
  3269.                 0,
  3270.                 0xFFFFFFFF,            // Max bytes to copy
  3271.                 InternalBuffers,
  3272.                 InternalBufferCount,
  3273.                 0);
  3274.         } //if
  3275.  
  3276.         if (NO_ERROR == ReturnValue){
  3277.             //Is this a overlapped operation.
  3278.             if (lpOverlapped){
  3279.                 if (lpCompletionRoutine
  3280.                         || (lpOverlapped->hEvent==NULL)
  3281.                         || ResetEvent ((HANDLE)((DWORD)lpOverlapped->hEvent&0xFFFFFFFE))) {
  3282.                     PDWORKERTHREAD  Thread = GetWorkerThread ();
  3283.                     if (Thread!=NULL) {
  3284.                         // Setup the user overlapped struct
  3285.                         lpOverlapped->Internal = WSS_OPERATION_IN_PROGRESS;
  3286.                         lpOverlapped->InternalHigh = 0;
  3287.                         ReturnValue = Thread->QueueOverlappedSendTo(
  3288.                             Socket,
  3289.                             InternalBuffers,
  3290.                             InternalBufferCount,
  3291.                             lpNumberOfBytesSent,
  3292.                             dwFlags,
  3293.                             lpTo,
  3294.                             iTolen,
  3295.                             lpOverlapped,
  3296.                             lpCompletionRoutine,
  3297.                             lpThreadId,
  3298.                             lpErrno);
  3299.                     }
  3300.                     else {
  3301.                         ReturnValue = SOCKET_ERROR;
  3302.                         *lpErrno = WSAENOBUFS;
  3303.                     }
  3304.                 }
  3305.                 else {
  3306.                     ReturnValue = SOCKET_ERROR;
  3307.                     *lpErrno = WSA_INVALID_PARAMETER;
  3308.                 }
  3309.             } //if
  3310.             else{
  3311.                 Provider = Socket->GetDProvider();
  3312.                 ProviderSocket = Socket->GetProviderSocket();
  3313.  
  3314.                 SetBlockingProvider (Provider);
  3315.                 ReturnValue = Provider->WSPSendTo(
  3316.                     ProviderSocket,
  3317.                     lpBuffers,
  3318.                     dwBufferCount,
  3319.                     lpNumberOfBytesSent,
  3320.                     dwFlags,
  3321.                     lpTo,
  3322.                     iTolen,
  3323.                     lpOverlapped,
  3324.                     lpCompletionRoutine,
  3325.                     lpThreadId,
  3326.                     lpErrno);
  3327.                 SetBlockingProvider (NULL);
  3328.                 gBufferManager->FreeBuffer (InternalBuffers, InternalBufferCount);
  3329.             } //else
  3330.         } //if
  3331.     } //if
  3332.  
  3333.     POSTAPINOTIFY(( DTCODE_WSPSendTo,
  3334.                     &ReturnValue,
  3335.                     gLibraryName,
  3336.                     &s,
  3337.                     &lpBuffers,
  3338.                     &lpNumberOfBytesSent,
  3339.                     &dwFlags,
  3340.                     &lpTo,
  3341.                     &iTolen,
  3342.                     &lpOverlapped,
  3343.                     &lpCompletionRoutine,
  3344.                     &lpThreadId,
  3345.                     &lpErrno));
  3346.  
  3347.     return(ReturnValue);
  3348. }
  3349.  
  3350.  
  3351.  INT
  3352. WSPAPI
  3353. WSPSetSockOpt(
  3354.     IN SOCKET s,
  3355.     IN INT level,
  3356.     IN INT optname,
  3357.     IN const char FAR *optval,
  3358.     IN INT optlen,
  3359.     OUT INT FAR *lpErrno
  3360.     )
  3361. /*++
  3362. Routine Description:
  3363.  
  3364.     Set a socket option.
  3365.  
  3366. Arguments:
  3367.  
  3368.     s       - A descriptor identifying a socket.
  3369.  
  3370.     level   - The  level  at  which the option is defined; the supported levels
  3371.               include   SOL_SOCKET.   (See  annex  for  more  protocol-specific
  3372.               levels.)
  3373.  
  3374.     optname - The socket option for which the value is to be set.
  3375.  
  3376.     optval  - A  pointer  to  the  buffer  in which the value for the requested
  3377.               option is supplied.
  3378.  
  3379.     optlen  - The size of the optval buffer.
  3380.  
  3381.     lpErrno - A pointer to the error code.
  3382.  
  3383. Return Value:
  3384.  
  3385.     If  no  error  occurs, WSPSetSockOpt()  returns  0.  Otherwise, a value of
  3386.     SOCKET_ERROR  is  returned, and  a  specific  error  code  is available in
  3387.     lpErrno.
  3388.  
  3389. --*/
  3390. {
  3391.     INT ReturnValue;
  3392.     PDSOCKET     Socket;
  3393.     PDPROVIDER   Provider;
  3394.     SOCKET       ProviderSocket;
  3395.  
  3396.  
  3397.     if (PREAPINOTIFY(( DTCODE_WSPSetSockOpt,
  3398.                        &ReturnValue,
  3399.                        gLibraryName,
  3400.                        &s,
  3401.                        &level,
  3402.                        &optname,
  3403.                        &optval,
  3404.                        &optlen,
  3405.                        &lpErrno)) ) {
  3406.         return(ReturnValue);
  3407.     }
  3408.  
  3409.     //
  3410.     // Get our DSOCKET object
  3411.     //
  3412.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  3413.         s,
  3414.         (DWORD*)&Socket,
  3415.         lpErrno);
  3416.     if (SOCKET_ERROR != ReturnValue){
  3417.         Provider = Socket->GetDProvider();
  3418.         ProviderSocket = Socket->GetProviderSocket();
  3419.  
  3420.         ReturnValue = Provider->WSPSetSockOpt(
  3421.             ProviderSocket,
  3422.             level,
  3423.             optname,
  3424.             optval,
  3425.             optlen,
  3426.             lpErrno);
  3427.     } //if
  3428.  
  3429.     POSTAPINOTIFY(( DTCODE_WSPSetSockOpt,
  3430.                     &ReturnValue,
  3431.                     gLibraryName,
  3432.                     &s,
  3433.                     &level,
  3434.                     &optname,
  3435.                     &optval,
  3436.                     &optlen,
  3437.                     &lpErrno));
  3438.  
  3439.     return(ReturnValue);
  3440.  
  3441. }
  3442.  
  3443.  
  3444.  
  3445. INT
  3446. WSPAPI
  3447. WSPShutdown(
  3448.     IN SOCKET s,
  3449.     IN INT how,
  3450.     OUT INT FAR *lpErrno
  3451.     )
  3452. /*++
  3453. Routine Description:
  3454.  
  3455.     Disable sends and/or receives on a socket.
  3456.  
  3457. Arguments:
  3458.  
  3459.     s       - A descriptor identifying a socket.
  3460.  
  3461.     how     - A  flag  that describes what types of operation will no longer be
  3462.               allowed.
  3463.  
  3464.     lpErrno - A pointer to the error code.
  3465.  
  3466. Return Value:
  3467.  
  3468.     If  no  error  occurs, WSPShutdown()  returns  0.   Otherwise, a value of
  3469.     SOCKET_ERROR  is  returned, and  a  specific  error  code  is available in
  3470.     lpErrno.
  3471.  
  3472. --*/
  3473. {
  3474.     INT ReturnValue;
  3475.     PDSOCKET     Socket;
  3476.     PDPROVIDER   Provider;
  3477.     SOCKET       ProviderSocket;
  3478.  
  3479.  
  3480.     if (PREAPINOTIFY(( DTCODE_WSPShutdown,
  3481.                        &ReturnValue,
  3482.                        gLibraryName,
  3483.                        &s,
  3484.                        &how,
  3485.                        &lpErrno)) ) {
  3486.         return(ReturnValue);
  3487.     }
  3488.  
  3489.     //
  3490.     // Get our DSOCKET object
  3491.     //
  3492.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  3493.         s,
  3494.         (DWORD*)&Socket,
  3495.         lpErrno);
  3496.     if (SOCKET_ERROR != ReturnValue){
  3497.         Provider = Socket->GetDProvider();
  3498.         ProviderSocket = Socket->GetProviderSocket();
  3499.         DEBUGF( DBG_TRACE,
  3500.                 ("Shutdown socket %X\n",s));
  3501.  
  3502.         ReturnValue = Provider->WSPShutdown(
  3503.             ProviderSocket,
  3504.             how,
  3505.             lpErrno);
  3506.     } //if
  3507.  
  3508.     POSTAPINOTIFY(( DTCODE_WSPShutdown,
  3509.                     &ReturnValue,
  3510.                     gLibraryName,
  3511.                     &s,
  3512.                     &how,
  3513.                     &lpErrno));
  3514.  
  3515.     return(ReturnValue);
  3516. }
  3517.  
  3518.  
  3519.  
  3520. SOCKET
  3521. WSPAPI
  3522. WSPSocket(
  3523.     IN int af,
  3524.     IN int type,
  3525.     IN int protocol,
  3526.     IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
  3527.     IN GROUP g,
  3528.     IN DWORD dwFlags,
  3529.     OUT INT FAR *lpErrno
  3530.     )
  3531. /*++
  3532. Routine Description:
  3533.  
  3534.     Initialize  internal  data  and  prepare sockets for usage.  Must be called
  3535.     before any other socket routine.
  3536.  
  3537. Arguments:
  3538.  
  3539.     lpProtocolInfo - Supplies  a pointer to a WSAPROTOCOL_INFOA struct that
  3540.                      defines  the characteristics of the socket to be created.
  3541.  
  3542.     g              - Supplies  the identifier of the socket group which the new
  3543.                      socket is to join.
  3544.  
  3545.     dwFlags        - Supplies the socket attribute specification.
  3546.  
  3547.     lpErrno        - Returns the error code
  3548.  
  3549. Return Value:
  3550.  
  3551.     WSPSocket() returns zero if successful.  Otherwise it returns an error code
  3552.     as outlined in the SPI.
  3553.  
  3554. --*/
  3555. {
  3556.     INT                 ReturnValue;
  3557.     INT                 NextProviderSocket;
  3558.     PDPROVIDER          Provider;
  3559.     PDSOCKET            Socket;
  3560.     DWORD                ThisProviderCatalogEntryId;
  3561.     PPROTO_CATALOG_ITEM    BaseProviderCatalogEntry;
  3562.  
  3563.     // Debug/Trace stuff
  3564.     if (PREAPINOTIFY(( DTCODE_WSPSocket,
  3565.                        &ReturnValue,
  3566.                        gLibraryName,
  3567.                        &af,
  3568.                        &type,
  3569.                        &protocol,
  3570.                        &lpProtocolInfo,
  3571.                        &g,
  3572.                        &dwFlags,
  3573.                        &lpErrno)) ) {
  3574.         return(ReturnValue);
  3575.     }
  3576.  
  3577.  
  3578.     //
  3579.     // Get the catlog entry for the next provider in the chain
  3580.     //
  3581.     ReturnValue = gProviderCatalog->FindNextProviderInChain(
  3582.         lpProtocolInfo,
  3583.         &Provider,
  3584.         &BaseProviderCatalogEntry);
  3585.  
  3586.     if (NO_ERROR==ReturnValue) {
  3587.         WSAPROTOCOL_INFOW    ProtocolInfo;
  3588.         LPWSAPROTOCOL_INFOW    lpPassedInfo;
  3589.  
  3590.         // If next provider is base, get it its own protocol info
  3591.         if (BaseProviderCatalogEntry) {
  3592.             ProtocolInfo = *BaseProviderCatalogEntry->GetProtocolInfo();
  3593.             // Carefully restore reserved field.
  3594.             ProtocolInfo.dwProviderReserved = lpProtocolInfo->dwProviderReserved;
  3595.             lpPassedInfo = &ProtocolInfo;
  3596.         }
  3597.         else
  3598.             lpPassedInfo = lpProtocolInfo;
  3599.  
  3600.         ReturnValue = Provider->WSPSocket(
  3601.             af,
  3602.             type,
  3603.             protocol,
  3604.             lpPassedInfo,
  3605.             g,
  3606.             dwFlags,
  3607.             lpErrno);
  3608.  
  3609.         if (ReturnValue != INVALID_SOCKET){
  3610.             NextProviderSocket = ReturnValue;
  3611.  
  3612.             //
  3613.             // Create our socket object
  3614.             //
  3615.  
  3616.             Socket = new DSOCKET;
  3617.             if (Socket){
  3618.                 ThisProviderCatalogEntryId = 
  3619.                     gProviderCatalog->GetLocalProvider()->GetProtocolInfo()->dwCatalogEntryId;
  3620.  
  3621.                 ReturnValue = gUpCallTable.lpWPUCreateSocketHandle(
  3622.                     ThisProviderCatalogEntryId,
  3623.                     (DWORD) Socket,
  3624.                     lpErrno);
  3625.                 DEBUGF( DBG_TRACE,
  3626.                         ("Socket Returning Socket %X\n", ReturnValue));
  3627.  
  3628.                 if (INVALID_SOCKET != ReturnValue){
  3629.                     Socket->Initialize(
  3630.                         Provider,
  3631.                         NextProviderSocket,
  3632.                         lpProtocolInfo->dwCatalogEntryId,
  3633.                         ReturnValue);
  3634.  
  3635.                 } //if
  3636.                 else{
  3637.                     delete(Socket);
  3638.                 } //else
  3639.             } //if
  3640.         } //if
  3641.         else{
  3642.             *lpErrno = ReturnValue;
  3643.             ReturnValue = INVALID_SOCKET;
  3644.         } //else
  3645.     } //if
  3646.     else{
  3647.         *lpErrno = ReturnValue;
  3648.         ReturnValue = INVALID_SOCKET;
  3649.     } //else
  3650.  
  3651.     // Debug/Trace stuff
  3652.     POSTAPINOTIFY(( DTCODE_WSPSocket,
  3653.                     &ReturnValue,
  3654.                     gLibraryName,
  3655.                     &af,
  3656.                     &type,
  3657.                     &protocol,
  3658.                     &lpProtocolInfo,
  3659.                     &g,
  3660.                     &dwFlags,
  3661.                     &lpErrno));
  3662.  
  3663.     return(ReturnValue);
  3664. }
  3665.  
  3666.  
  3667.  
  3668.  
  3669. INT
  3670. WSPAPI
  3671. WSPStringToAddress(
  3672.     IN     LPWSTR AddressString,
  3673.     IN     INT AddressFamily,
  3674.     IN     LPWSAPROTOCOL_INFOW lpProtocolInfo,
  3675.     OUT    LPSOCKADDR lpAddress,
  3676.     IN OUT LPINT lpAddressLength,
  3677.     IN OUT LPINT lpErrno )
  3678. /*++
  3679.  
  3680. Routine Description:
  3681.  
  3682.     WSPStringToAddress() converts a human-readable string to a socket address
  3683.     structure (SOCKADDR) suitable for pass to Windows Sockets routines which
  3684.     take such a structure.  If the caller wishes the translation to be done by
  3685.     a particular provider, it should supply the corresponding WSAPROTOCOL_INFO
  3686.     struct in the lpProtocolInfo parameter.
  3687.  
  3688. Arguments:
  3689.  
  3690.     AddressString - points to the zero-terminated human-readable string to
  3691.                     convert.
  3692.  
  3693.     AddressFamily - the address family to which the string belongs.
  3694.  
  3695.     lpProtocolInfo - (optional) the WSAPROTOCOL_INFO struct for a particular
  3696.                      provider.
  3697.  
  3698.     Address - a buffer which is filled with a single SOCKADDR structure.
  3699.  
  3700.     lpAddressLength - The length of the Address buffer.  Returns the size of
  3701.                       the resultant SOCKADDR structure.
  3702.  
  3703. Return Value:
  3704.  
  3705.     The return value is 0 if the operation was successful.  Otherwise the value
  3706.     SOCKET_ERROR is returned.
  3707.  
  3708. --*/
  3709. {
  3710.     INT                 ReturnValue;
  3711.     PDPROVIDER          Provider;
  3712.     PPROTO_CATALOG_ITEM    BaseProviderCatalogEntry;
  3713.  
  3714.     if (PREAPINOTIFY(( DTCODE_WSPAddressToString,
  3715.                        &ReturnValue,
  3716.                        gLibraryName,
  3717.                        &AddressString,
  3718.                        &AddressFamily,
  3719.                        &lpProtocolInfo,
  3720.                        &lpAddress,
  3721.                        &lpAddressLength,
  3722.                        &lpErrno)) ){
  3723.         return(ReturnValue);
  3724.     } //if
  3725.  
  3726.     //
  3727.     // Get the catlog entry for the next provider in the chain
  3728.     //
  3729.     ReturnValue = gProviderCatalog->FindNextProviderInChain(
  3730.         lpProtocolInfo,
  3731.         &Provider,
  3732.         &BaseProviderCatalogEntry);
  3733.  
  3734.     if (NO_ERROR == ReturnValue){
  3735.         ReturnValue = Provider->WSPStringToAddress(
  3736.             AddressString,
  3737.             AddressFamily,
  3738.             BaseProviderCatalogEntry
  3739.                 ? BaseProviderCatalogEntry->GetProtocolInfo()
  3740.                 : lpProtocolInfo,
  3741.             lpAddress,
  3742.             lpAddressLength,
  3743.             lpErrno);
  3744.     } //if
  3745.  
  3746.     POSTAPINOTIFY(( DTCODE_WSPAddressToString,
  3747.                     &ReturnValue,
  3748.                     gLibraryName,
  3749.                     &AddressString,
  3750.                     &AddressFamily,
  3751.                     &lpProtocolInfo,
  3752.                     &lpAddress,
  3753.                     &lpAddressLength,
  3754.                     &lpErrno));
  3755.  
  3756.     return(ReturnValue);
  3757.  
  3758. }
  3759.  
  3760.  
  3761.  
  3762. int
  3763. WSPAPI
  3764. WSPStartup(
  3765.     WORD wVersion,
  3766.     LPWSPDATA lpWSPData,
  3767.     LPWSAPROTOCOL_INFOW lpProtocolInfo,
  3768.     WSPUPCALLTABLE UpcallTable,
  3769.     LPWSPPROC_TABLE lpProcTable )
  3770. /*++
  3771.  
  3772. Routine Description:
  3773.  
  3774.     Initiate use of a WinSock service provider by a client.
  3775.  
  3776. Arguments:
  3777.  
  3778.     wVersionRequested - The highest version of WinSock SPI support that the
  3779.                         caller  can use. The high order byte specifies the
  3780.                         minor version (revision) number; the low-order byte
  3781.                         specifies the major version number.
  3782.  
  3783.     lpWSPData - A pointer to the WSPDATA data structure that is to receive
  3784.                 details of the WinSock service provider.
  3785.  
  3786.     lpProtocolInfo - A pointer to a WSAPROTOCOL_INFO struct that defines the
  3787.                      characteristics of the desired protocol.  This is
  3788.                      especially useful when a single provider DLL is capable of
  3789.                      instantiating multiple different service providers.
  3790.  
  3791.     UpcallTable    The WinSock 2 DLLs upcall dispatch table.
  3792.  
  3793.     lpProcTable - A pointer to the table of SPI function pointers.
  3794.  
  3795.  
  3796.  
  3797. Return Value:
  3798.  
  3799.  
  3800. --*/
  3801. {
  3802.     HMODULE            hWS2_32;
  3803.     INT                ReturnCode;
  3804.  
  3805.     EnterCriticalSection(&gInitCriticalSection);
  3806.  
  3807.     ReturnCode = NO_ERROR;
  3808.  
  3809.     // Save the WinSock2 upcall table
  3810.     gUpCallTable = UpcallTable;
  3811.  
  3812.     if (gStartupCount == 0){
  3813.         ReturnCode = WSAVERNOTSUPPORTED;
  3814.         // This is the first time that WSPStartup() has been called so lets get
  3815.         // ourselves ready to do bussiness
  3816.  
  3817.         // First check for new exported function
  3818.         hWS2_32 = GetModuleHandle (TEXT("ws2_32.dll"));
  3819.         if (hWS2_32!=NULL) {
  3820.             lpWPUCompleteOverlappedRequest = 
  3821.                 (LPWPUCOMPLETEOVERLAPPEDREQUEST)
  3822.                     GetProcAddress (hWS2_32, "WPUCompleteOverlappedRequest");
  3823.  
  3824.  
  3825.             if (lpWPUCompleteOverlappedRequest!=NULL) {
  3826.                 ReturnCode = WSASYSNOTREADY;
  3827.  
  3828.  
  3829.                 // Initialize the sockets
  3830.                 DSOCKET::DSocketClassInitialize ();
  3831.  
  3832.                 //
  3833.                 // Init the provider catalog
  3834.                 //
  3835.                 gProviderCatalog = new DCATALOG;
  3836.                 if (gProviderCatalog){
  3837.                     ReturnCode = gProviderCatalog->Initialize();
  3838.                 } //if
  3839.  
  3840.                 //
  3841.                 // Init the buffer manager
  3842.                 //
  3843.                 if (NO_ERROR == ReturnCode){
  3844.                     gBufferManager = new DBUFFERMANAGER;
  3845.                     if (gBufferManager){
  3846.                         ReturnCode = gBufferManager->Initialize();
  3847.                         // If we succeded incremant the startup count
  3848.                         if (NO_ERROR == ReturnCode){
  3849.                             gStartupCount++;
  3850.                         } //if
  3851.                     } //if
  3852.                 } //if
  3853.             } //if
  3854.         } // if
  3855.     } // if
  3856.     LeaveCriticalSection(&gInitCriticalSection);
  3857.  
  3858.     if (ReturnCode==NO_ERROR) {
  3859.         //
  3860.         // Fill in the clients proceedure table with our entry points.
  3861.         //
  3862.  
  3863.         lpProcTable->lpWSPAccept = WSPAccept;
  3864.         lpProcTable->lpWSPAddressToString = WSPAddressToString;
  3865.         lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
  3866.         lpProcTable->lpWSPBind = WSPBind;
  3867.         lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
  3868.         lpProcTable->lpWSPCleanup = WSPCleanup;
  3869.         lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
  3870.         lpProcTable->lpWSPConnect = WSPConnect;
  3871.         lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
  3872.         lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
  3873.         lpProcTable->lpWSPEventSelect = WSPEventSelect;
  3874.         lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
  3875.         lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
  3876.         lpProcTable->lpWSPGetSockName = WSPGetSockName;
  3877.         lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
  3878.         lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
  3879.         lpProcTable->lpWSPIoctl = WSPIoctl;
  3880.         lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
  3881.         lpProcTable->lpWSPListen = WSPListen;
  3882.         lpProcTable->lpWSPRecv = WSPRecv;
  3883.         lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
  3884.         lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
  3885.         lpProcTable->lpWSPSelect = WSPSelect;
  3886.         lpProcTable->lpWSPSend = WSPSend;
  3887.         lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
  3888.         lpProcTable->lpWSPSendTo = WSPSendTo;
  3889.         lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
  3890.         lpProcTable->lpWSPShutdown = WSPShutdown;
  3891.         lpProcTable->lpWSPSocket = WSPSocket;
  3892.         lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
  3893.  
  3894.     }
  3895.  
  3896.     // Set the version info
  3897.     lpWSPData->wVersion = MAKEWORD(2,2);
  3898.     lpWSPData->wHighVersion = MAKEWORD(2,2);
  3899.  
  3900.     return(ReturnCode);
  3901. }
  3902.  
  3903.  
  3904. BOOL
  3905. PASCAL FAR
  3906. WSPTransmitFile (
  3907.     IN SOCKET hSocket,
  3908.     IN HANDLE hFile,
  3909.     IN DWORD nNumberOfBytesToWrite,
  3910.     IN DWORD nNumberOfBytesPerSend,
  3911.     IN LPOVERLAPPED lpOverlapped,
  3912.     IN LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
  3913.     IN DWORD dwReserved
  3914.     ) {
  3915.     PDSOCKET    Socket;
  3916.     INT            Errno, ReturnValue;
  3917.     PDPROVIDER    Provider;
  3918.     SOCKET        ProviderSocket;
  3919.     //
  3920.     // Get our DSOCKET object
  3921.     //
  3922.     ReturnValue = gUpCallTable.lpWPUQuerySocketHandleContext(
  3923.         hSocket,
  3924.         (DWORD*)&Socket,
  3925.         &Errno);
  3926.  
  3927.     if (SOCKET_ERROR != ReturnValue){
  3928.         if (lpOverlapped) {
  3929.             if ((lpOverlapped->hEvent==NULL)
  3930.                     || ResetEvent ((HANDLE)((DWORD)lpOverlapped->hEvent&0xFFFFFFFE))) {
  3931.                 PDWORKERTHREAD  Thread = GetWorkerThread ();
  3932.                 if (Thread!=NULL) {
  3933.                     // Setup the user overlapped struct
  3934.                     lpOverlapped->Internal = WSS_OPERATION_IN_PROGRESS;
  3935.                     lpOverlapped->InternalHigh = 0;
  3936.                     ReturnValue = Thread->QueueOverlappedTransmitFile(
  3937.                             Socket,
  3938.                             hFile,
  3939.                             nNumberOfBytesToWrite,
  3940.                             nNumberOfBytesPerSend,
  3941.                             lpOverlapped,
  3942.                             lpTransmitBuffers,
  3943.                             dwReserved,
  3944.                             &Errno);
  3945.                 }
  3946.                 else {
  3947.                     ReturnValue = SOCKET_ERROR;
  3948.                     Errno = WSAENOBUFS;
  3949.                 }
  3950.             }
  3951.             else {
  3952.                 ReturnValue = SOCKET_ERROR;
  3953.                 Errno = WSA_INVALID_PARAMETER;
  3954.             }
  3955.         }
  3956.         else {
  3957.             Provider = Socket->GetDProvider ();
  3958.             ProviderSocket = Socket->GetProviderSocket ();
  3959.             ReturnValue = Provider->TransmitFile (
  3960.                         ProviderSocket,
  3961.                         hFile,
  3962.                         nNumberOfBytesToWrite,
  3963.                         nNumberOfBytesPerSend,
  3964.                         lpOverlapped,
  3965.                         lpTransmitBuffers,
  3966.                         dwReserved,
  3967.                         &Errno);
  3968.         }
  3969.     }
  3970.     if (ReturnValue==NO_ERROR)
  3971.         return TRUE;
  3972.     else {
  3973.         SetLastError (Errno);
  3974.         return FALSE;
  3975.     }
  3976. }
  3977.  
  3978.